const_cast,static_cast,dynamic_cast,reinterpret_cast的区别

C++继承了C中的隐式和显式转换的方式。但这种转换并不是安全和严格的,

加上C++本身对象模型的复杂性,C++增加了四个显示转换的关键字。(C++是强类型语言)

经过编码测试,小结如下:

const_cast:仅用于去掉完全同类型的const,volatile约束,不能含有任何其它类型的转换,若不含约束也可以相当于没转换
static_cast:使用类型可在继承的方向上向上或向下转换,不进行安全检查。
      子类转父类,值、引用、指针形式均可,其中指针还可以是常量
      父类转子类,值不可以,引用和指针均可,子类中的多余成员值是乱码
      不支持不同无关类之间的转换
dynamic_cast:动态转换,使用类型可在继承的方向上向上或向下转换,进行安全检查。
      子类转父类,值不可以,引用、指针均可,其中指针还可以是常量
      父类转子类,值不可以,引用可通过编译,但运行失败。指针可通过编译,该转换也能运行,但是后面再调用方法时会检查类型,判断是否失败。
      不支持不同无关类之间的转换
reinterpret_cast:强制类型转换
      子类转父类,值不可以,引用、指针形式均可,其中指针还可以是常量
      父类转子类,值不可以,引用和指针均可,子类中的多余成员值是乱码
      不同无关类之间的转换,值不可以,引用和指针均可,方法正常调用但多余成员值是乱码

  1 // test  static_cast dynamic_cast
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 using namespace std;
  5 class Base
  6 {
  7     public:
  8     Base () {b=0;}
  9     Base(int i){b=i;}
 10     int b;
 11     void display(){ printf("Base %d \n",b);}
 12     virtual void display_v() { printf("Base virtual method %d \n",b);}
 13     void set(int i) {b=i;}
 14 };
 15 class Derived: public Base
 16 {
 17     public:
 18     Derived () {b=0;d=-1;}
 19     Derived(int i,int j):Base(i){d=j;}
 20     int d;
 21     void display() { printf("Derived %d %d \n",b,d);}
 22     void display_v() { printf("Derived virtual method %d %d \n",b,d);}
 23 };
 24 class Otherclass
 25 {
 26     public:
 27     Otherclass(){}
 28     int other;
 29 };
 30 int main()
 31 {
 32     Base *bbp,bb(4);
 33     Derived *ddp,dd(7,6);
 34     Base *newb=new Base(2);
 35     Derived *newd=new Derived(3,1);
 36     Otherclass ot,*otp;
 37 ////test1:static_cast
 38
 39 //    bb=static_cast<Base> (dd);
 40 //    bb.display();// Base 7
 41 //    bb.display_v();//Base virtual method 7
 42 //    bb=static_cast<Base&> (dd);
 43 //    bb.display();// Base 7
 44 //    bb.display_v();//Base virtual method 7
 45 //    newb=static_cast<Base*> (newd);
 46 //    newb->display();// Base 3
 47 //    newb->display_v();//Derived virtual method 3 1
 48 //    dd=static_cast<Derived> (bb);//error 无构造函数可以接受源类型,或构造函数重载决策不明确
 49 //    dd=static_cast<Derived&> (bb);//right
 50 //    dd.display();// Derived 4 6625256
 51 //    dd.display_v();//Derived virtual method 4 6625256
 52 //    newd=static_cast<Derived*> (newb);//right
 53 //    newd->display();//Derived 2 838805478
 54 //    newd->display_v();//Base virtual method 2
 55
 56 //       bb=static_cast<Base> (ot);//error 无法从“Otherclass”转换为“Base” 无构造函数可以接受源类型,或构造函数重载决策不明确
 57 //       bb=static_cast<Base&> (ot);//error 无法从“Otherclass”转换为“Base &” 引用的 static_cast 和 safe_cast 只能用于有效初始化或用于相关类之间的左值转换
 58 //      bbp=static_cast<Base*> (otp);//error无法从“Otherclass *”转换为“Base *” 与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
 59
 60 ////test2:static_cast
 61 //  bb=dynamic_cast<Base> (dd);//error 目标类型必须是指向已定义类的指针或引用
 62 //    bb=dynamic_cast<Base&> (dd);
 63 //    bb.display();// Base 7
 64 //    bb.display_v();//Base virtual method 7
 65 //    newb=dynamic_cast<Base*> (newd);
 66 //    newb->display();// Base 3
 67 //    newb->display_v();//Derived virtual method 3 1
 68 //    dd=dynamic_cast<Derived> (bb);//error 目标类型必须是指向已定义类的指针或引用
 69 //    dd=dynamic_cast<Derived&> (bb);//error 编译通过,运行失败//即使bb已成为Derived对象的引用,运行也失败
 70 //    newd=dynamic_cast<Derived*> (newb);//编译通过,//
 71 //    newd->display();//运行失败,//若newb实际指向Derived对象则成功运行
 72 //       bb=dynamic_cast<Base> (ot);//error  目标类型必须是指向已定义类的指针或引用
 73 //       bb=dynamic_cast<Base&> (ot);//error “Otherclass”不是多态类型
 74 //      bbp=dynamic_cast<Base*> (otp);//error “Otherclass”不是多态类型
 75
 76
 77 ////test3:reinterpret_cast
 78 //    bb=reinterpret_cast<Base> (dd);//error 转换要求构造函数或用户定义的转换运算符,而该运算符不能由 const_cast 或 reinterpret_cast 使用
 79 //    bb=reinterpret_cast<Base&> (dd);
 80 //    bb.display();// Base 7
 81 //    bb.display_v();//Base virtual method 7
 82 //    newb=reinterpret_cast<Base*> (newd);
 83 //    newb->display();// Base 3
 84 //    newb->display_v();//Derived virtual method 3 1
 85 //    dd=reinterpret_cast<Derived> (bb);// error 转换要求构造函数或用户定义的转换运算符,而该运算符不能由 const_cast 或 reinterpret_cast 使用
 86 //    dd=reinterpret_cast<Derived&> (bb);//right
 87 //    dd.display();// Derived 4 6625256
 88 //    dd.display_v();//Derived virtual method 4 6625256
 89 //    newd=reinterpret_cast<Derived*> (newb);//right
 90 //    newd->display();//Derived 2 838805478
 91 //    newd->display_v();//Base virtual method 2
 92
 93 //       bb=reinterpret_cast<Base> (ot);//error 无法从“Otherclass”转换为“Base” 转换要求构造函数或用户定义的转换运算符,而该运算符不能由 const_cast 或 reinterpret_cast 使用
 94 //       bb=reinterpret_cast<Base&> (ot);//right
 95 //        bb.display();//Base 20257015
 96 //      bbp=reinterpret_cast<Base*> (otp);//right
 97 //      bbp->display();//Base 418153452
 98
 99 ////test4:const_cast
100     const Base cbb(4);
101     Base *const cbbp=new Base(2);
102     const Derived cdd(7,6);
103     Derived *const cddp=new Derived(3,1);
104 //  bb=const_cast<Base> (cbb);//error 转换要求构造函数或用户定义的转换运算符,而该运算符不能由 const_cast 或 reinterpret_cast 使用
105 //  bb=const_cast<Base&> (*cbbp);//right
106 //  bb=const_cast<Base&> (cbb);//right
107 //  bb=const_cast<Base&> (cdd);//error 无法从“const Derived *”转换为“Base *”,类型的差异不在于限定符;不能单独使用 const_cast
108 //  bb=static_cast<Base&> (cbb);  //error 无法从“const Base”转换为“Base &” 引用的 static_cast 和 safe_cast 只能用于有效初始化或用于相关类之间的左值转换
109 //  bb=dynamic_cast<Base&> (cbb);  //不能使用“dynamic_cast”从“const Base”转换到“Base &”
110 //  bb=reinterpret_cast<Base&> (cbb);  //error  无法从“const Base *”转换为“Base *” 转换丢失限定符
111
112 //
113 //  bbp=const_cast<Base*> (cbbp);//right
114 //  bbp=const_cast<Base*> (cddp);//无法从“Derived *const ”转换为“Base *” 类型的差异不在于限定符;不能单独使用 const_cast
115 //  bbp=static_cast<Base*> (cbbp);//right
116 //  bbp->set(2);
117 //  bbp->display();//Base 2
118 //  bbp=dynamic_cast<Base*> (cbbp);// right
119 //  bbp->set(2);
120 //  bbp->display();//Base 2
121 //  bbp=reinterpret_cast<Base*> (cbbp);// right
122 //  bbp->set(2);
123 //  bbp->display();//Base 2
124
125     volatile Base vbb(4);
126     Base *volatile vbbp=new Base(2);
127     volatile Derived vdd(7,6);
128     Derived *volatile vddp=new Derived(3,1);
129 //  bb=const_cast<Base> (vbb);//error 无法从“volatile Base”转换为“Base”  转换要求构造函数或用户定义的转换运算符,而该运算符不能由 const_cast 或 reinterpret_cast 使用
130 //  bb=const_cast<Base&> (vbb);//right
131 //  bb=const_cast<Base&> (vdd);//error 无法从“volatile Derived *”转换为“Base *”  类型的差异不在于限定符;不能单独使用 const_castt
132 //
133 //  bbp=const_cast<Base*> (vbbp);//right
134 //  bbp=const_cast<Base*> (vddp);//无法从“Derived *volatile ”转换为“Base *” 类型的差异不在于限定符;不能单独使用 const_cast
135
136     int a=3;
137     const double cd=3.0;
138     //a=const_cast<int> (cd);//无法从“const double”转换为“int”  转换是有效的标准转换,可以隐式执行或通过使用 static_cast、C 样式转换或函数样式转换执行
139     return 0;
140 }

附:摘自http://blog.csdn.net/starryheavens/article/details/4617637

1.1       reinpreter_cast

用法:reinpreter_cast<type-id> (expression)

type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。

这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换。reinpreter_cast是特意用于底层的强制转型,导致实现依赖(就是说,不可移植)的结果。

int n=9;

// reinterpret_cast 仅仅是复制 n 的比特位到 d,因此d 包含无用值。

double d=reinterpret_cast<double & > (n);

1.2       const_cast

用法:const_cast<type_id> (expression)

用于修改类型的const或volatile属性。除了const 或volatile修饰之外,type_id和expression的类型是一样的,一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型,而C不提供消除const的机制(已验证)。

常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

1.3       static_cast

用法:static_cast < type-id > ( expression )

该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它允许执行任意的隐式转换和相反转换动作。主要有如下几种用法:

1)用于基本数据类型之间的转换,如把int转换成char,non-const 对象转型为 const 对象(这里相反方向不可以,C++只有const_cast可以)。

2)把空指针转换成目标类型的指针。(之前的做法是用强制转换(type-id*))

3)把任何类型的表达式转换成void类型。

4)应用到类的指针上,它允许子类类型的指针转换为父类类型的指针(upercasting这是一个有效的隐式转换);也能够执行相反动作,即转换父类为它的子类(downcasting),这种转换的安全性需要开发人员来保证(主要是在非上下转型中)。

class Base {};

class Derived : public Base {};

Base *a = new Base;

Derived *b = NULL;

b = static_cast<Derived *>(a); //可以通过编译,但存在安全隐患(如访问//Derived的成员)

注意:

1.static_cast不能转换掉expression的const、volitale、或者__unaligned属性。

2.在非基本类型或上下转型中,被转换的父类需要检查是否与目的类型相一致,否则,如果在两个完全不相干的类之间进行转换,将会导致编译出错。

1.4       dynamic_cast

只用于对象的指针和引用,主要用于执行“安全的向下转型”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。

当用于多态类型时(包含虚函数),它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里(即隐式转换的相反过程),dynamic_cast根据RTTI信息检查操作是否有效。即在转换时dynamic_cast会检查转换是否能返回一个被请求的有效的完整对象。这种检查不是语法上的,而是真实情况的检查。检测在运行时进行,如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL。

时间: 2024-10-02 11:24:26

const_cast,static_cast,dynamic_cast,reinterpret_cast的区别的相关文章

C++中static_cast/const_cast/dynamic_cast/reinterpret_cast的区别和使用

C风格的强制转换较简单,如将float a转换为int b,则可以这样:b = (int)a,或者b=int(a). C++类型转换分为隐式类型转换和显示类型转换. 隐式类型转换又称为标准转换,包括以下几种情况: (1).算术转换:在混合类型的算术表达式中,最宽的数据类型成为目标转换类型: (2).一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型: (3).将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型: (4).从一个函数返回一个表达式,

static_cast, dynamic_cast, reinterpret_cast, const_cast区别比较

隐式转换(implicit conversion) short a=2000; int b; b=a; short是两字节,int是四字节,由short型转成int型是宽化转换(bit位数增多),编译器没有warning,如下图所示.宽化转换(如char到int,int到long long,int到float,float到double,int到double等)构成隐式转换,编译器允许直接转换. 但若反过来 double a=2000; short b; b=a; 此时,是从8字节的double型

Qt 中C++ static_cast 和 reinterpret_cast的区别

1.C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作.因此,被做为隐式类型转换使用.比如: int i; float f = 166.7f; i = static_cast<int>(f); 此时结果,i的值为166. 2.C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型.所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释.比如: int i; char *p = "This is a

static_cast和reinterpret_cast

static_cast和reinterpret_cast 相同点:都是暴力转换,从一个类型转换为另一个类型,对于类指针不会保证安全性 static_cast和reinterpret_cast的区别主要在于多重继承,比如 1 2 3 4 5 6 7 8 9 10 11 class A {     public:     int m_a; }; class B {     public:     int m_b; }; class C : public A, public B {}; 那么对于以下代

c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast

c++强制类型转换:dynamic_cast.const_cast .static_cast.reinterpret_cast 博客分类: C/C++ CC++C#编程数据结构 dynamic_cast:   通常在基类和派生类之间转换时使用const_cast:   主要针对const和volatile的转换static_cast:   一般的转换(no run-time check)通常,如果你不知道该用哪个,就用这个.   reinterpret_cast:   用于进行没有任何关联之间的

static_cast, dynamic_cast和reinterpret_cast的区别和应用 [转]

其实不仅仅是一个转载,还是一个融合 今天的一个考题为:#include <iostream>using namespace std; class BClass{public:    BClass(){};    virtual ~BClass(){};    virtual void OutPut(int i){cout<<"BClass::ouput is "<<i<<endl;} };class son1:public BClass{

static_cast 、const_cast、dynamic_cast、reinterpret_cast 关键字简单解释

static_cast .const_cast.dynamic_cast.reinterpret_cast 关键字简单解释: Static_cast 静态类型转换 ①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换. 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的: 进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的. ②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum.这种转换的安全性也要开发人员来保

【转】C++中static_cast, dynamic_cast, const_cast用法/使用情况及区别解析

原文链接:http://blog.csdn.net/bzhxuexi/article/details/17021559 首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型. int ival = 3;double dval = 3.14159; ival + dval;//ival被

static_cast, dynamic_cast, const_cast探讨

C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为"标准转换",包括以下几种情况:1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型. int ival = 3;double dval = 3.14159;ival + dval;//ival被提升为double类型 2)一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型 int *pi = 0; // 0被转化为int