编程中经常遇到子类和父类的类型转换,总结了一下:
1 static_cast
相当于C语言中的强制转换:(类型)表达式或类型(表达式),用于各种隐式转换
非const转const、void*转指针、int和char相互转换
用于基类和子类之间的指针和引用转换,非指针直接报错
向上转化是安全的,如果向下转能(指针或引用)成功但是不安全,结果未知;
2 dynamic_cast
用于动态类型转换。只能用于含有虚函数的类,必须用在多态体系种,用于类层次间的向上和向下转化。只能转指针或引用。向下转化时,如果是非法的对于指针返回NULL,对于引用抛异常。
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
如果没有virtual方法进行下行转换(指针或引用)会直接报错。
(1)指针类型
举例,Base为包含至少一个虚函数的基类,Der是Base的共有派生类,如果有一个指向Base的指针bp,我们可以在运行时将它转换成指向Der的指针,代码如下:
if(Der *dp = dynamic_cast<Der *>(bp)){
//使用dp指向的Derived对象
}
else{
//使用bp指向的Base对象
}
值得注意的是,在上述代码中,if语句中定义了dp,这样做的好处是可以在一个操作中同时完成类型转换和条件检查两项任务。
(2)引用类型
因为不存在所谓空引用,所以引用类型的dynamic_cast转换与指针类型不同,在引用转换失败时,会抛出std::bad_cast异常,该异常定义在头文件typeinfo中。
void f(const Base &b){
try{
const Der &d = dynamic_cast<const Base &>(b);
//使用b引用的Der 对象
}
catch(std::bad_cast){
//处理类型转换失败的情况
}
}
3 reinterpret_cast
(重解释转换)几乎什么都可以转,比如将int转指针,可能会出问题,尽量少用;随意的转换编译都会通过,但是不安全的转换运行时会异常
错误的使用reinterpret_cast很容易导致程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。
reinterpret_cast不能转换掉表达式的const
可以用在将void*转换为int类型
4 const_cast
常量指针被转化成非常量的指针,并且仍然指向原来的对象;
常量引用被转换成非常量的引用,并且仍然指向原来的对象;
const_cast一般用于修改底指针。如const char * ptr形式。
const int a = 20;
int * ptr = const_cast<int*>(&a);
*ptr = 2; // a还是20, ptr指向的内存值为2