标签:
C++的类型转换分为两种:隐式转换和显示转换。class B { public: int num; B(int a) { num=a; } } B show(B b) { return b; }show(5);//这里也发生了隐式转换,将5转换为B类型的(B)5;
下面对他们--进行小小的总结:
1、static_cast(编译器在编译期处理)
转换格式:static_cast<type-id>(expression)。
将expression转换为type-id类型,type-id和expression必须是指针、引用、算术类型或枚举类型。一般的转换(no run-time check),不提供运行时的检查来确保转换的安全性。 C程序员大概都喜欢用强制类型转换,它虽然优缺点,但是考虑到它的灵活我们还是用的不亦乐乎。大多数情况下我们都会转换成功,只有少量的情况下才会转换失败,失败了怎么办,这时候就用到了dynamic_cast了。这里的“少量情况”是这样的,如果有多继承的类对象,你在某些情况下要得到对象的指针,而你又将其转换为某种类型,但是由于C++对象类型的多态性(可以有多种类型),你又不确定一定会成功(运行的时候才确定其类型),此时可以利用dynamic_cast,充分利用C++的运行时检查机制。
例如:
class A{...}; class B:public A{...}; class C:public B{...}; void Fun1(B* pB) { A* pA = (A*)pB; C* pC = (C*)pB; }Fun1函数使用强制类型转换将pB转换为A*或C*,看出什么的问题了吗?
但如果是这样呢: Fun1(new B); 类型的转换成功,pC不会为NULL,因为强转总是会成功的,但是达不到我们的目的,因为当使用到pC指针时就程序就悲剧了,崩溃(具体解决办法后面有详细的分析).
如果情况更糟: Fun1((B*)0X00005678); //0X00005678是一个随机值
pA,pC都不会是NULL,再说一遍强制类型转换总是能够成功的,重要的事情说两遍。但使用这两个指针时程序肯定崩溃.当然你可以使用异常处理机制来处理这样的错误,不过这有点大才小用的感觉,最好能够找到一种能够检查出类型转换能否成功的办法,这时dynamic_cast就能大显身手了.详解正解请往下看。
dynamic_cast的转换格式:dynamic_cast<type-id>(expression)
将expression转换为type-id类型,type-id必须是类的指针、类的引用或者是void*;并且expression和type-id的类型必须一致;
在运行期,会检查这个转换是否可能。仅能应用于指针或者引用,不支持内置数据类型,因为只有指针和引用才能实现多态,赋值和传值就会出现对象的分割,不会实现多态。通常在基类和派生类之间转换时使用 。基本用法如下:
T1 obj;#include <iostream> using namespace std; class A{}; classB:public A{}; int main() { B *b=new B; A *a=dynamic_cast<A*>(b); //Safe and success! B *b=dynamic_cast<B*>(b); //Safe and success! void *vp=dynamic_cast<void *>(c);//success vp points to an object C; system("pause"); return 0; }static_cast和dynamic_cast具有相同的效果,而这种上行转换也为隐式转换;和我们的定义:A *a=new C;一样;只是多加了一个dynamic_cast转换符而已。
#include <iostream> using namespace std; class A{}; class B:public A{}; class C:public A{}; class D:public B,public C{}; int main() { D *d=new D; A *a=dynamic_cast<A *>(d);//这是因为BC都继承了A,那么从D转换到A就有两条路可以走,DBA或者DCA,这样的话,计算机就不知道怎么走了,那么a=NULL; system("pause"); return 0; }(2)(down cast)向下转型:下行转换时dynamic_cast具有类型检查的功能,比static_cast安全;在多态类之间的转换主要用dynamic_cast,因为类型提供了
#include <iostream> using namespace std; class A{}; class B:public A{}; int main() { A *a=new B; A *aa=new A; B *a1=dynamic_cast<B*>(a); // a1不为NULL,a本来指向B,Safe and success! B *a2=dynamic_cast<B*>(aa) // error,aa指向A,并不指向B ,返回NULL,即a2=NULL; system("pause"); return 0; }
看到这里,回到上面的问题:具体做法就是:
A* pA = dynamic_cast<A*>pB;// upcast. if (NULL == pA){...} //OK,不为NULL; C* pC = dynamic_cast<C*>pB;// downcast. if (NULL == pC){...} //error,显然为空NULL;dynamic_cast < ObjectType-ID* > ( ObjectType*)
横向转型的时候一定要注意是否有继承关系,如果没有继承关系的两个类是不能转换的。
例子如下:
class Shape {}; class Rollable {}; class Circle : public Shape, public Rollable {}; class Square : public Shape {}; //cross cast fail Shape *pShape1 = new Square(); Rollable *pRollable1 = dynamic_cast<Rollable*>(pShape1);//pRollable为NULL //cross cast success Shape *pShape2 = new Circle(); Rollable *pRollable2 = dynamic_cast<Rollable*>(pShape2);//pRollable不为NULL
3、const_cast (编译器在编译期处理)
const_cast的转换格式:const_cast <type-id> (expression)注意常量对象只能调用常量函数,常量函数只能输出,不能改变成员属性的值,所以这里需要const_cast来转换我非常量的指针对象来进行下一步的操作。
#include <iostream> using namespace std; class A { public: A():num(10) { cout<<"A"<<endl; } int num; }; int main() { const A *a=new A; A *a3=new A; cout<<a->num<<endl; //a->num=100; //error;因为常量对象不允许改变类的成员属性; A *aa=const_cast<A *>(a); aa->num=100;//OK,经过const_cast的转化,aa不是常量对象; cout<<a->num<<endl; const A &a1=*a; //a1->num=200; //error;常量对象的引用也不能改变成员属性; A &a2=const_cast<A&>(*a); a2.num=200; cout<<a2.num<<endl;//OK,经过const_cast的转化,a2不是常量对象的引用; //现在a2和aa都是指向同一个对象。 //A a4=const_cast<A>(*a3); //error,,不能直接使用const_cast对非const,volatile和nuligned去掉该属性。 const char* p = "123"; char* c = const_cast<char*>(p); <span> </span><pre name="code" class="cpp"> c[0] = 1; //error,表面上通过编译去掉了const性,但是操作其地址时系统依然不允许这么做。char *pp="keepgoing";const char *p1=const_cast<const char *>(pp);system("pause");return 0;}
运行结果:
对于本身定义时为const的类型,即使你去掉const性,在你操作这片内容时候也要小心,只能r不能w操作,否则还是会出错。
const_cast操作不能在不同的种类间转换。相反,它仅仅把一个它作用的表达式转换成常量。它可以使一个本来不是const类型的数据转换成const类型的,或者把const属性去掉。尽量不要使用const_cast,如果发现调用自己的函数,竟然使用了const_cast,那就赶紧打住,重新考虑一下设计吧。reinterpret_cast的转换格式:reinterpret_cast <type-id> (expression)
用于进行没有任何关联之间的转换,比如一个字符指针转换为一个整形数。允许将任何指针类型转换为其它的指针类型;听起来很强大,但是也很不靠谱。它主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针,在实际开发中,先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原来的指针值;特别是开辟了系统全局的内存空间,需要在多个应用程序之间使用时,需要彼此共享,传递这个内存空间的指针时,就可以将指针转换成整数值,得到以后,再将整数值转换成指针,进行对应的操作。
博文资料参考:
http://riddickbryant.iteye.com/blog/547361
http://www.jb51.net/article/55968.htm
http://www.jb51.net/article/55885.htm
http://bbs.pediy.com/showthread.php?t=196996
http://www.cnblogs.com/weidagang2046/archive/2010/04/10/1709226.html
http://jetyi.blog.51cto.com/1460128/671256
dynamic_cast、static_cast、const_cast和reinterpret_cast的区别
标签:
原文地址:http://blog.csdn.net/gogokongyin/article/details/51317975