C++实例讲解四种类型转换的使用
C类型转换C语言风格的转换C语言提供了自己的一套转换规则有好处也有坏处。C语言的风格type_nameexpression;C语言提供了隐式类型转换和显式类型转换。显式类型转换一般也叫做强转隐式类型转换编译器完成如果转换不了就报错。而C语言类型转换的风格好处就是简单缺陷比如转换的可视性差显式类型转换的写法就只有一种难以精准的跟踪错误。char ch1.1char ch1在.cpp下都是合法的这就是隐式类型转换C语言下如果把一个结构体给int就会报错因为编译器不知道怎么去转C下可以通过实现operator int()实现类型转换或者提供合适的构造函数完成隐式类型转换下面以在.cpp中实现operator int()为例下面这段代码由于隐式类型转换导致了死循环C语言的类型转换其实已经足够完成需求了但是可视性不太好比如你不能在代码库中搜索它就一对括号怎么去搜索所以C提供了一套类型转换相当于语法糖了此外还会进行一些编译性检查比如dynamic_cast转换失败则返回空指针。但其实作用都是一样的。C风格的类型转换C标准为了增加类型转换的可见性提供了四种类型转化的方式。static_cast静态类型转换进行相关类型的转换但不能转换两个不相关的类型即编译器看到这个转换是行不通的就会报错。static_cast type-id ( expression )12345678intmain(){doublea (int)5.5 5.3;//结果是10.3doubleb static_castint(5.5) 5.3;cout a: a endl;cout b: b endl;return0;}转换不相关的类型reinterpret_cast很暴力的一个操作符由英文直译过来就是重新解释的转型。白话就是将一段内存重新解释。网上看到很多大佬的理解这里借用或掺杂自己的思想static_cast是做类型能做的转换不行编译器就报错告诉你这样是不合理的reinterpret_cast则是就算不能转换编译器你也别报错我心里有数。由于reinterpret_cast本质上是一个编译器指令所以实际动作完全取决于编译器失去了移植性。暴力归暴力但也是合理范围内的比如你把一个结构体硬塞给int肯定是不行的但是把结构体指针重新解释为int那是一点问题没有。此外reinterpret_cast重新解释的办法是把那一块内存的比特位全部复制下来重新解释。下面的例子把一个结构体指针解释为int再加上5.3。1234567891011structTest{inta;};intmain(){Test* t newTest;doublec reinterpret_castint(t) 5.3;cout c endl;return0;}const_cast删除变量的const属性一般和指针或引用连用123456789intmain(){constinta 1;//a是常变量在栈上int* p const_castint*(a);*p 2;cout a endl;cout *p endl;return0;}volatile const int a1;//打印的a就会是2volatile后编译器对访问该变量的代码不再优化。比如上面那句代码打印1就是因为编译器优化读取的a是从寄存器中读取的而不是内存。多线程中也有很多关于 volatile的应用。dynamic_castdynamic_cast安全的向下转型。多态的转换中向下转型父类转为子类用dynamic是安全的但是父类必须有虚函数,否则编译报错且只能用于指针或引用。向上转型子类给父类发生切割不需要转换。向下转型父类地址给子类指针需要类型转换由于是类型是子类指针但是给的地址是父类的如果用指针去访问子类独有的数据可能就会造成越界然后程序就可能崩了所以此时就需要dynamic_cast进行转换了因为dynamic_cast会检查父类指针是否指向的是这个子类如果是父类说明可能带来一些安全问题会转换失败返回空指针反之则实现转换。理解向下转型不安全有个例子男人是人但人不一定是男人男人派生自人男人的指针男人类型的指针强转人的地址此时如果通过男人指针去调用男人自己独有的特性就是越界因为实际上拿到的是人的地址并没有存储男人的特性也可以从空间大小上来解释人是父类空间更小男人是子类空间更大给的是小空间却有了访问大空间的能力所以可能造成越界所以是不安全的此外在一个父类有多个子类且需要类型转换时dynamic_cast也能起到作用举个例子123//父类是Entity子类是Player和Enemy e,player,enemy分别表示他们对应的实例化对象Entity* pplayer;Enemy* p1(Enemy*)p;//向下转型需要强转这样搞就出问题了p明明指向的是一个player现在类型为Enemy的指针居然指向了一个Player的对象如果对其内存进行了操作那后果是不可预料的。父类指针一开始指向一个父类对象再给到子类类型的指针存在越界的风险如果为了保证安全则需要检查。父类的指针指向子类对象向上转型再给到子类指针合理。所以建议使用dynamic_cast因为可以保证安全 转换失败返回空指针NULL。dynamic_cast的底层与RTTI有关借助RTTI拿到类型信息所以dynamic_cast更像一个函数因为不是编译指令所以会带来一些性能的损失。RTTI 是“Runtime Type Information”的缩写意思是运行时类型信息。RTTI存储了所有类型运行时的类型信息增加了开销但是可以让我们做更多的操作。dynamic_cast的底层就是借助了RTTI匹配具体的不太了解。VS可以关闭RTTI,但是也就不能用dynamic_cast了下面给一个代码例子123456789101112131415161718192021222324252627282930313233343536373839classEntity{public:virtualvoidPrint() {};//dynamic_cast使用的前提必须是父类有虚函数};classPlayer:publicEntity{};classEnemy :publicEntity{};voidCheck(void* p){if(p){cout 转换成功 endl;}else{cout 转换失败 endl;}}intmain(){Entity* e newEntity();Entity* actuallyPlayer newPlayer();//向上转型//安全的向下转型Player* player (Player*)actuallyPlayer;//向下转型需要转换类型Player* player2 dynamic_castPlayer*(actuallyPlayer);Check(player2); cout endl;//不安全的向下转型Player* player3 (Player*)e;Player* player4 dynamic_castPlayer*(e);Check(player4); cout endl;Entity* actuallyEnemy newEnemy();Player* player5 dynamic_castPlayer*(actuallyEnemy);Check(player5); cout endl;return0;}dynamic也常常利用返回值是否是空指针来判断指针具体指向谁。用dynamic_cast的地方其实也可以用static_cast不过static_cast不会进行安全检查,如果你很清楚其指向并且在安全的前提下为了减少程序开销那可以考虑用static_cast小结static_cast用于相关类型的转换reinterpret_cast用于重新解释内存很暴力用的时候心里要有数const_cast常用来取出const属性常与指针连用来修改const变量的值dynamic_cast在多态里提供安全的向下转换转换不安全就返回空指针只要对返回的指针进行判断我们就能知道此次转换安不安全了