标准C++引入了四种命名的强制类型转换:const_cast、static_cast、reinterpret_cast、dynamic_cast
(主要C风格的类型转换,隐式转换在某些情况下可能会存在问题,显示转换将所有情况混肴在一起,不够清晰)
const_cast
去常性转换,可以去除变量的常量性,多用于常量指针转化为非常量指针:const int *
==> int *
const int temp = 10;
int *ptr = const_cast<int *>(&temp);
*ptr = 20;
cout << temp << endl;//10
cout << *ptr << endl;//20
//编译器优化导致的结果
//编译器默认const修饰的变量无法修改,会将const修饰的变量放到寄存器中,当需要读取const变量时会直接从寄存器中进行读取,而上述代码实际修改的是内存中temp的值
//解决办法:可以用volatile(禁止编译器优化)进行修饰:volatile const int temp = 10;
static_cast
安全性高(使用居多),系统认为转换无问题则允许转换,反之拒绝转换
用于非多态类型之间的转换即静态转换,编译器隐式执行的类型转换都可以使用(比如char, short, int, double, unsigned int等类型之间的转换,或其他类型转换为void类型),是属于相近类型之间的转换(C语言的某些隐式类型转换可能会存在问题)
不能用于父类指针与子类指针之间的转换,没有运行时类型检查来保证转换的安全性
double a = 3.1415926;
int b = static_cast<int>(a);
reinterpret_cast
类似C强制转换,可以忽略类型间的差异,使用有危险,固使用时需小心,确保转换是安全的,用于不相近类型间的转换,一种类型转换为另一种类型(可以五花八门的进行转换,平台移植性较差),常用于指针间转换
int *a = new int(10);
char *b = reinterpret_cast<char *>(a);
int c = 20;
int d = reinterpret_cast<int>(&c);
dynamic_cast
运行时类型转换(用于RTTI信息转换),转换后必须是类的指针、引用或void*,常用于父类指针或引用转换为子类指针或引用(父类含有虚函数的类),具有类型检查功能
子类指针或引用转换为父类指针或引用是天然支持的(赋值兼容规则),无需转换
//dynamic_cast转换是安全的
//父类指针若是指向子类对象,使用dynamic_cast转换为子类指针是安全的,转换成功
//父类指针若是指向父类对象,使用dynamic_cast转换为子类指针则会失败(可能会访问到子类部分的资源,但父类没有),并返回空指针,引用会抛出异常
class A;
class B:public A
{};
A* a = new B();
B* b = dynamic_cast<B*>(a);