C语言的类型转换包括隐式类型转换和显示类型转换。当赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就会发生类型转化。
缺陷:C语言的转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。
C++的强制类型转换
标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符。
static_cast 相似类型的转换
用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用,但它不能用于两个不相关的类型进行转换。如整形数据之间相互转换。
static_cast<类型>(变量)
//c的写法 int a = 10; double b = (double)a;
reinterpret_cast 无关类型转换
reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型。如将整型转成指针。
reinterpret_cast<类型>(变量)
//c的写法 int a = 10; int* p = (int*)a;
const_cast
删除变量的const属性,方便赋值。
const_cast<类型>(变量)
const int a = 10;//a是常变量,真的不能修改的才放在常量区
int* p = const_cast<int*>(&a);//c的写法 int* p = (int*)&a;
*p = 20;
cout << a << endl;//10
cout << *p << endl;//20
编译器对const类型会做优化,它认为a是const类型,不会被修改就会把a放到寄存器里去,cout是流插入直接去寄存器取,*p到内存里去取。为了防止优化,就可以加个volatile
保持内存可见性,这样编译器每次都会到内存里取,这样结果就都是20、20.
dynamic_cast
dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)。
dynamic_cast<类型>(变量)
- 向上转型:子类对象指针/引用->父类指针/引用,这个行为是安全的(不需要转换,赋值兼容规则)
- 向下转型:父类对象指针/引用->子类指针/引用,这个行为有可能出问题。因为父类对象的指针或引用是可以接收父类对象或者子类对象(多态),说明它既可以访问父类对象的成员又可以访问子类对象的成员,当传的是父类对象,但是它却访问了子类对象的成员,就是越界访问了。要用
dynamic_cast
转才是安全的。
注意:
-
dynamic_cast
只能用于父类含有虚函数的类,即多态类型; -
dynamic_cast会先检查是否能转换成功,转换成功就继续,不能则返回0;
注意:强制类型转换关闭或挂起了正常的类型检查,每次使用强制类型转换前,程序员应该仔细考虑是否还有其他不同的方法达到同一目的,如果非强制类型转换不可,则应限制强制转换值的作用域,以减少发生错误的机会。强烈建议:避免使用强制类型转换
RTTI
Run-time Type identification的简称,即:运行时类型识别。
C++通过以下方式来支持RTTI:
- typeid运算符
- dynamic_cast运算符
- decltype