C++的四种类型转换
- C++语言级别提供的四种类型转换方式:
- const_cast: 去掉常量属性的一个类型转换(const_cast<>必须放指针或者引用类型)
- static_cast: 提供编译器认为安全的类型转换(最常用的类型转换,无任何联系的类型之间的转换会被编译器否定)
- reinterpret_cast: 类似于C风格的强制类型转换,不安全
- dynamic_cast: 主要用在继承结构中,可以支持RTTI类型识别的上下转换
int main()
{
const int a = 10;
// int* p = &a; p无法指向常量的地址
int* p = (int*)&a; // C风格的类型强转,去掉常量属性
// 可以随意使用指针的解引用 char*p = (char*)&a
int* p2 = const_cast<int*>(&a); // c++风格
// 去掉常量属性,<>里的类型必须和&a的类型是保持一致的, 如果希望转成char*, char*p = const_cast<char*>(&a); 编译会出错
// 比较安全
// const_cast<>必须放指针或者引用类型
// static_cast 基类类型<=>派生类型 可以使用static_cast类型转换,但是转换之后的安全性需要由开发者来维护
int a = 10;
char b = static_cast<int>(a);// int和char类型之间是由联系的,编译时允许转换
/*
把int*强转成short*
int* p = nullptr;
short*c = static_cast<short*>(p) int* 和short*之间是没有任何联系的,编译器不允许强转
short* c = (short*c)p; c风格的类型强转是可以的
*/
// reinterpret_cast<>类似C风格的类型转换,但是不安全
int* p = nullptr;
short* c = reinterpret_cast<short*>(p); // 强制类型转换, 不安全
return 0;
}
语言级别的转换方式无法查看其源码实现,但是查看编译后的汇编指令时会发现,C++的类型转换和C的类型强转的汇编指令是一致的,但是在编译阶段就有所不同了)
dynamic_cast类型转换的使用
:
class Base
{
public:
virtual void func() = 0;
};
class Derive1 : public Base
{
public:
void func() { cout << "call Derive1::func" << endl; }
};
// Derive02中定义一个新的功能:derive02func()
class Derive2 : public Base
{
public:
void func() { cout << "call Derive2::func" << endl; }
void derive02func()
{
cout << "call Derive2:: derive02func " << endl;
}
};
/* 我们希望如果p指向的是其他派生类型,就执行p->func(),若p指向Derive2类型,就调用
p->derive02func(),显然需要去进行类型的判断(检查)
*/
void showFunc(Base *p)
{// 当p指向Derive2类型的时候,执行derive02func(),指向其他派生类对象时执行func
// dynamic_cast会检查p指针所指向的是否是一个Derive2类型的对象
// 怎么检查? 通过p->vfptr->vftable的RTTI信息,如果是,dynamic_cast转换成功,返回Derive2对象地址
// 如果不是,则返回nullptr
Derive2* pd2 = dynamic_cast<Derive2*>(p);
if (pd2 != nullptr)
{
pd2->derive02func();
}
else
{
p->func();
}
}
static_cast是编译时期的类型转换, dynamic_cast是运行时期的类型转换 (支持RTTI信息识别)