C++基础:四种类型强转
作者:
jokerlove
,
2022-09-07 15:44:50
,
所有人可见
,
阅读 250
都什么年代了还在用传统类型转换
/*
const_cast: 去掉常量属性
static_cast: 提供编译器认为安全的类型转换,没有联系的类型之间不可实现强转
reinterpret_cast: 类似C风格的强转(都什么年代了还在用传统强转)
dynamic_cast: 主要用在继承结构中,可以支持RTTI类型识别的上下转换
传统强转与四种cast的区别:
同:二者在底层实现一致
异:cast只会做编译器认为正确的类型转换,而传统强转可以实现任何类型之间的转换,相对不够安全
注意:为什么说int*转换为double*不安全?
double*指针内存有8字节,而被转元素只有4字节,反过来也不安全
const_cast:
移除常量const属性,但不能改变其类型,常量是int,强转类型也要是int,接收指针也是int
并且const_cast<这里必须是同类型的指针/引用>
static_cast:运行时不做类型检查RTTI!但编译时会做类型检查
不强制指针类型时,与传统强转一样。使用指针时会检查类型
父类<->子类之间的转换可以通过static_cast实现,但正确与否就需要开发者判断了
不能更改const,static属性
reinterpret_cast:
指针类型和非指针类型都可以强转,但同样不够安全
dynamic_cast:基于继承
假设这样一个场景:要求调用子类C中的newFunc()而非func()
显然外部接口的A* p只能去调用合适的虚函数,没有办法调用C中普通成员函数
因此需要dynamic将p指针强转为C类型的指针tmp,需要先判断原来p指针指向什么类型
1如果p指针没有指向C类型,返回nullptr
2如果p指针指向C类型,返回C类型的tmp指针,进行后续调用普通函数的操作
注意区分static_cast和dynamic_cast:
在上面的例子中,statict也可以和dynamic一样实现父类指针强转为子类类型
但是不能判断传入的到底是C类型还是B类型的指针,一股脑都给你转为C类型了
*/
class A
{
public:
virtual void func() = 0;
};
class B :public A
{
public:
void func() { cout << "B" << endl; }
};
class C :public A
{
public:
void func() { cout << "C" << endl; } // 假设不需要调用C的虚函数
void newFunc() { cout << "newC" << endl; } // 转而调用普通函数newFunc()
};
void showFunc(A* p) // 外界接口,里面发生动态绑定
{
// 设计需求:如果传入其他子类对象,调用虚函数func(),如果传入C类对象,调用newFunc()
// 所以需要先识别A* p接收的对象类型,再按序调用,此时可以使用dynamic_cast
// dynamic会检查指针p的vfptr->vftable->RTTI类型。是C类型返回C类型对象地址,否则返回nullptr
// 此时tmp可能是强转为C类型的p指针,也可能是nullptr
C* tmp = dynamic_cast<C*>(p);
//C* tmp = static_cast<C*>(p);
// 注意static确实可以实现父子类型的强转,但是不能判断传参类型B还是C,只是强转,调用也是错的
if (tmp != nullptr)
tmp->newFunc(); // tmp现在为C类指针,可以调用类内合适的函数
else
p->func(); // 否则说明传入的对象不涉及C类型,更不需要调用C中的普通函数
}
int main()
{
const int a = 10;
//int* a1 = &a; // 错误,指针不能指向常量,加const可以
int* a2 = (int*)&a; // 但是可以传统强转为对应类型再指向
int* a3 = const_cast<int*>(&a); // 使用const_cast将常量强转为int*,在底层等同上面a2
//int* a4 = const_cast<int>(&a); // <里面必须是同类型的指针/引用>
int b = 10;
char b1 = (int)b;
char b2 = static_cast<int>(b); // 没用指针时,二者一致,都是从int转为char
int* c = nullptr;
double* c1 = (double*)c; // 但是加了指针就有区别了,传统强转不会判断类型是否合理,所以可以实现
//double* c2 = static_cast<double*> (c); // 不可以cast强转两个不相干的指针类型
double* c2 = reinterpret_cast<double*> (c); // 但是reinterpret可以做到
B bb;
C cc;
showFunc(&bb); // 不涉及调用C的普通方法
showFunc(&cc); // 使用dynamic强转为C类型,进而调用C中的普通方法
return 0;
}