const_cast,static_cast,dynamic_cast,reinterpret_cast的区别(转)
原文:https://www.cnblogs.com/fancy-xt/p/5339177.html
C++继承了C中的隐式和显式转换的方式。但这种转换并不是安全和严格的,
加上C++本身对象模型的复杂性,C++增加了四个显示转换的关键字。(C++是强类型语言)
经过编码测试,小结如下:
const_cast:仅用于去掉完全同类型的const,volatile约束,不能含有任何其它类型的转换,若不含约束也可以相当于没转换
static_cast:使用类型可在继承的方向上向上或向下转换,不进行安全检查。
子类转父类,值、引用、指针形式均可,其中指针还可以是常量
父类转子类,值不可以,引用和指针均可,子类中的多余成员值是乱码
不支持不同无关类之间的转换
dynamic_cast:动态转换,使用类型可在继承的方向上向上或向下转换,进行安全检查。
子类转父类,值不可以,引用、指针均可,其中指针还可以是常量
父类转子类,值不可以,引用可通过编译,但运行失败。指针可通过编译,该转换也能运行,但是后面再调用方法时会检查类型,判断是否失败。
不同无关类之间的转换均不能运行,但多态类可通过编译
reinterpret_cast:强制类型转换,不改变原有数据,只是重新解释内存
子类转父类,值不可以,引用、指针形式均可,其中指针还可以是常量
父类转子类,值不可以,引用和指针均可,子类中的多余成员值是乱码
不同无关类之间的转换,值不可以,引用和指针均可,重新解释内存
可以这样记忆:
update:
首先是子类转父类,无论static_cast还是dynamic_cast,指针/引用均可转。但对于dynamic_cast,值不能转,而static_cast可以
然后是父类转子类,对于static_cast,值XXX,指针/引用XXXX。对于dynamic_cast,值XXX,指针/引用XXXX
------------------------------------------
1. 严格性: dynamic_cast > static_cast 父类转子类 > 子类转父类
2. 只有严格性最低的情况(即使用static_cast将子类转父类)允许值转换,其他情况都不可以进行值转换
3. 指针、引用的转换:
- 子类转父类的情况:
直接转,没有任何问题 (无论 dynamic_cast,static_cast都可)
- 父类转子类的情况:
可以转,可以通过编译,可以运行成功,但访问子类部分是乱码 (static_cast)
可以转,可以通过编译,但是运行会失败 (dynamic_cast)
另:可以使用static_cast将一个左值转换为右值引用(c++ primer P612)
对于含有虚函数的父子类(多态基类)之间的转换,一定要用dynamic_cast(如果用dynamic_cast进行没有虚函数的父子类之间的转换会出错);
其他没有虚函数的父子类(非多态基类)用static_cast进行转换
eg:
#include<iostream> using namespace std; class Base { }; class Derived: public Base {}; int main() { Base *base_ptr = new Derived; Derived *derived_ptr = dynamic_cast<Derived*>(base_ptr); if(derived_ptr != NULL) cout<<"It is working"; else cout<<"cannot cast Base* to Derived*"; return 0; } // 运行结果:cannot cast Base* to Derived*
在添加虚拟方法之后,可以使用:
#include<iostream> using namespace std; class Base { virtual void function() { //空函数 } }; class Derived: public Base {}; int main() { Base *base_ptr = new Derived; Derived *derived_ptr = dynamic_cast<Derived*>(base_ptr); if(derived_ptr != NULL) cout<<"It is working"; else cout<<"cannot cast Base* to Derived*"; return 0; } // 运行结果:It is working
注意对能成功进行的含virtual方法的类,通过引用转换和指针转换后对virtual方法的调用不同,假设转换前为pref_class转换后为post_class,则:
通过引用转化调virtual方法实际是调用post_class中对应方法的;
通过指针转换调post_class中virtual指针相对存放位置对应pref_class相对位置的指针对应的方法(若该位置指向不是方法,运行失败),形参不一致会自动补全(一般是乱码)或删减