static_cast
static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可以用。
但static_cast不能用于两个不相关的类型进行转换。
double d = 12.34; int a = static_cast<int>(d);
reinterpret_cast
用于将一种类型转换为另外一种类型。
int a = 10; int* pa = static_cast<int*>(a);
这样是会报错的,因为从
int
类型转换到了int*
,属于不相关的类型转换了。这种情况下就只能使用reinterpret_cast了。
int a = 10; int* pa = reinterpret_cast<int*>(a);
const_cast
const_cast最常用的用途就是删除变量的const属性,方便赋值
const int a = 10; int* pa = const_cast<int*>(&a); *pa = 3; cout << a << endl; cout << *pa << endl;
但为什么输出是10和3呢?
因为编译器做了优化,直接把a的值存在寄存器当中了,虽然内存中a的值确实改变了,但是寄存器当中的没有改变,编译器他也不会去内存当中去找。
加上**
volatile
**关键字即可
volatile const int a = 10; int* pa = const_cast<int*>(&a); *pa = 3; cout << a << endl; cout << *pa << endl;
dynamic_cast
用于将一个父类对象的指针/引用转换为子类对象的指针或者引用。
向上转型:子类变为父类(不存在转换,编译器兼容)
向下转型:父类转换为子类
注意:
dynamic_cast只能用于父类含有虚函数的类。
dynamic_cast会检查是否能转换成功,不能会返回0。
父类要转换为子类是不被允许的,因为父类无法访问到子类的内容,会导致越界访问。
子类是可以转换为父类的,不存在越界行为。
class A { public: virtual void f(){} public: int _a = 0; }; class B : public A { public: int _b = 1; }; // A*指针pa有可能指向父类,有可能指向子类 void fun(A* pa) { // 如果pa是指向子类,那么可以转换,转换表达式返回正确的地址 // 如果pa是指向父类,那么不能转换,转换表达式返回nullptr B* pb = dynamic_cast<B*>(pa); // 安全的 //B* pb = (B*)pa; // 不安全 if (pb) { cout << "转换成功" << endl; pb->_a++; pb->_b++; cout << pb->_a << ":" << pb->_b << endl; } else { cout << "转换失败" << endl; pa->_a++; cout << pa->_a << endl; } } int main(void) { A aa; B bb; fun(&aa); fun(&bb); return 0; }
还有如下场景:
class A1 { public: virtual void f(){} public: int _a1 = 0; }; class A2 { public: virtual void f(){} public: int _a2 = 0; }; class B : public A1, public A2 { public: int _b = 1; }; int main(void) { B bb; A1* ptr1 = &bb; A2* ptr2 = &bb; cout << ptr1 << endl; cout << ptr2 << endl << endl; B* pb1 = (B*)ptr1; B* pb2 = (B*)ptr2; cout << pb1 << endl; cout << pb2 << endl << endl; B* pb3 = dynamic_cast<B*>(ptr1); B* pb4 = dynamic_cast<B*>(ptr2); cout << pb3 << endl; cout << pb4 << endl << endl; return 0; }