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相对位置的指针对应的方法(若该位置指向不是方法,运行失败),形参不一致会自动补全(一般是乱码)或删减

posted @ 2023-05-04 23:33  大黑耗  阅读(159)  评论(0编辑  收藏  举报