【目录】
举例: static_cast 用于基本类型之间、基本类型指针和空指针间的转换
c语言中我们经常使用类似于 int a =(int)3.14等这种强制类型转换
标准c++的类型转换符:static_cast 、dynamic_cast、 reindivter_cast、 const_cast, 以下分别介绍他们的用法以及举例说明
以下代码编译运行环境:codeblock with gcc in win7(x64)
【1】static_cast
用法:static_cast < type-id > ( exdivssion )
该运算符把exdivssion转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类和子类之间指针或引用的转换。
进行上行转换(把子类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast 不能转换掉exdivssion的const、volitale、或者__unaligned属性。
msdn官方解释:http://msdn.microsoft.com/en-us/library/c36yw7x9(v=vs.80).aspx
用法:dynamic_cast < type-id > ( exdivssion )
该运算符把exdivssion转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;
如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引用,那么exdivssion也必须是一个引用。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast 的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast 更安全。
msdn官方解释:http://msdn.microsoft.com/en-us/library/cby9kycs(v=vs.80).aspx
需要注意的是如果基类中不含虚函数,dynamic_cast 下行转换编译会出错
1 #include<iostream> 2 using namespace std; 3 4 class father 5 { 6 public: 7 void fun1() 8 { 9 cout<<"this is father fun1 call\n"; 10 } 11 virtual void fun() 12 { 13 cout<<"this is father fun call\n"; 14 } 15 }; 16 17 class son: public father 18 { 19 public: 20 void fun2() 21 { 22 cout<<"this is son fun2 call\n"; 23 } 24 void fun() 25 { 26 cout<<"this is the son fun call\n"; 27 } 28 int k; 29 }; 30 31 int main() 32 { 33 father *pf, f; 34 son *ps, s; 35 36 pf = &f;// 基类的指针指向基类对象 37 ps = static_cast<son *>(pf);//这种转换是不安全的,行为是不确定的 38 if(ps != NULL) 39 { 40 ps->fun(); //在本文编译环境下,执行父类的fun 41 //本文编译环境下,一下语句可以执行 42 ps->fun2(); 43 ps->k = 1; 44 } 45 ps = dynamic_cast<son *>(pf);//转换后ps = NULL 46 if(ps == NULL) 47 cout<<"dynamic_cast: ps = NULL\n"; 48 cout<<"-----------------------------------------------------------------\n"; 49 pf = &s; //基类指针开始指向子类对象 50 //此时,两种转换都是安全的 51 ps = static_cast<son *>(pf); 52 if(ps != NULL) 53 { 54 ps->fun(); 55 ps->fun2(); 56 ps->k = 1; 57 } 58 ps = dynamic_cast<son *>(pf);//转换后ps = NULL 59 if(ps != NULL) 60 { 61 ps->fun(); 62 ps->fun2(); 63 ps->k = 2; 64 } 65 }
结果:
1 //类定义同上 2 int main() 3 { 4 father *pf, f; 5 son *ps, s; 6 7 ps = &s;// 子类的指针指向子类对象 8 //此时两种转换都是安全的 9 pf = static_cast<father *>(ps); 10 if(pf != NULL) 11 { 12 pf->fun(); 13 } 14 pf = dynamic_cast<father *>(ps); 15 if(pf != NULL) 16 { 17 pf->fun(); 18 } 19 20 }
举例: static_cast 用于基本类型之间、基本类型指针和空指针间的转换(不能用于基本类型指针之间转换)。
注意:基本类型由于表示数值范围的不同,因此需要用户保证转换的安全。另外dynamic_cast不能用于此类转换
1 int main() 2 { 3 //基本类型间的转换,需要用户保证安全 4 int a = 1000; 5 char c = static_cast<char>(a);//不安全,1000超过了char的表示范围 6 cout<<c<<endl;//输出空 7 a = 49; 8 c = static_cast<char>(a);//安全,输出字符‘1’ 9 cout<<c<<endl; 10 //c = dynamic_cast<char>(a); 错误 11 cout<<"-----------------------------------------------------------------\n"; 12 //void *和基本类型指针的转换,需要用户保证转换安全 13 a = 49; 14 void *pv; 15 pv = &a; 16 int *pi = static_cast<int *>(pv);//void * 转换为int * 17 cout<<*pi<<endl; //输出49 18 //pi = dynamic_cast<int *>(pv); 错误 19 char *pc = static_cast<char *>(pv);//void *转char* 20 cout<<*pc<<endl;//输出字符‘1’ 21 void *pv2 = static_cast<void *>(pc);// char * 转void * 22 cout<<*((char *)pv2)<<endl;////输出字符‘1’ 23 }
用法:reinterpret_cast<type-id> (exdivssion)
reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。按照reinterpret的字面意思“重新解释”,即对数据的比特位重新解释。
IBM的C++指南 里明确告诉了我们reinterpret_cast可以,或者说应该在什么地方用来作为转换运算符:
总结来说:reinterpret_cast用在任意指针(或引用)类型之间的转换;以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小。
注意:static_cast 不能转换掉exdivssion的const、volitale、或者__unaligned属性。
msdn官方解释:http://msdn.microsoft.com/en-us/library/e0w9f63b(v=vs.80).aspx
1 int main() 2 { 3 int a = 49; 4 int *pi = &a; 5 char *pc = reinterpret_cast<char*>(pi);//int * 到char *,用户自己安全 6 cout<<*pc<<endl; //输出字符"1" 7 unsigned long b = reinterpret_cast<unsigned long>(pc);//char * 转 unsigned long 8 cout<<b<<endl;//输出pc指向地址(即a的地址)对应的整数 9 int *pi2 = reinterpret_cast<int *>(b);//unsigned long 转 int* 10 cout<<*pi2<<endl; //输出49 11 }
用法:const_cast<type-id> (exdivssion)
该运算符用来修改类型的const、volatile、__unaligned属性。除了const 、volatile、__unaligned修饰之外, type_id和exdivssion的类型是一样的。
常量指针被转化成非常量指针,并且仍然指向原来的对象;
常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。
msdn官方解释:http://msdn.microsoft.com/en-us/library/bz6at95h(v=vs.80).aspx
1 int main() 2 { 3 const int a = 100; 4 int *b = const_cast<int *>(&a);//const int * 转int * 5 cout<<*b<<endl; //输出100 6 cout<<&a<<" "<<b<<endl; //两者值相同,表明b指向a的地址,只是const属性变了 7 }
总结:
类指针或引用的上行转换static_cast 和 dynamic_cast 都可以
类指针或引用的下行转换用dynamic_cast并且判断转换后是否为空
基本数据类型之间的转换用static_cast, 但是由于数值范围的不同,需要用户保证转换的安全性
不同类型之间的指针或引用的转换用reinterpret_cast,它的本质是对指向内存的比特位的重解释
消除数据的const、volatile、__unaligned属性,用const_cast
【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3175217.html