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。