static_cast
static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可以用。
但static_cast不能用于两个不相关的类型进行转换。
double d = 12.34;
int a = static_cast<int>(d);
cout << a << endl;
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;
}