您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 冶金工业 > C++中的四种转型操作符
C++中的四种转型操作符分类:C++之技术2014-08-1100:09164人阅读评论(0)收藏举报c++转型编译器宏exception在详细介绍C++中的四种转型操作符之前,我们先来说说旧式转型的缺点:①它几乎允许将任何类型转换为任何其他类型,这是十分拙劣的。如果每次转型都能够更精确地指明意图,则更好。②旧式转型难以辨识。旧式转型的语法结构是由一对小括号加上一个对象名称组成,而小括号和对象名称在C++的任何地方都有可能被使用。为解决C旧式转型的缺点,C++导入了4个新的转型操作符:static_cast、const_cast、dynamic_cast、reinterpret_cast。下面我来一一分析这四种转型操作符。1)static_caststatic_cast基本上拥有与C旧式转型相同的威力与意义,以及相同的限制。例如,不能够利用static_cast将一个struct转型为int,或将一个double转型为pointer;这些都是C旧式转型动作原本就不可以完成的任务。static_cast甚至不能够移除表达式的常量性。inta,b;...doublec=static_castdouble(a)/b;2)const_castconst_cast用来改变表达式中的常量性(constness)或变易性(volatileness)。使用const_cast,便是对人类(以及编译器)强调,通过这个转型操作符,我们唯一想改变的是某物的常量性或变易性。如果将const_cast应用于上述以为的用途,那么转型动作会被拒绝。下面看一个例子:classWidget{...};classSpecialWidget:publicWidget{...};voidupdate(SpecialWidget*psw);SpecialWidgetsw;//sw是个non-const对象constSpecialWidget&csw=sw;//csw却是一个代表sw的reference,并视之为一个const对象update(&csw);//错误!不能讲constSpecialWidget*传给一个需要SpecialWidget*的函数update(const_castSpecialWidget*(&csw));//可!&csw的常量性被去除了。也因此,csw(亦即sw)在此函数中可被更改。update((SpecialWidget*)&csw);//情况同上,但使用的是较难辨识的c旧式转型语法Widget*pw=newSpecialWidget;update(pw);//错误!pw的类型是Widget*,但update()需要的却是SpecialWidget*。update(const_castSpecialWidgt*(pw));//错误!const_cast只能用来影响常量性或变易性,无法进行继承体系的向下转型动作。3)dynamic_cast①dynamic_cast用来执行继承体系中”安全地向下转型或跨系转型动作“。也就是说你可以利用dynamic_cast,将”指向baseclassobjects的pointers或references“转型为”指向derived(或siblingbase)classobjects的pointers或references“,并得知转型是否成功。如果转型失败,会以一个null指针(当转型对象是指针)或一个exception(当转型对象是reference)表现出来:Widget*pw;...update(dynamic_castSpecialWidget*(pw));//很好,传给update()一个指针,指向pw所指的SpecialWidget----如果pw真的指向这样的东西;否则传过去的将是一个null指针voidupdateViaRef(SpecialWidget&rsw);updateViaRef(dynamic_castSpecialWidget&(*pw));//很好,传给updateViaRef()的是pw所指的SpecialWidget----如果pw真的指向这样的东西;否则抛出一个exceptiondynamic_cast只能用来助你巡航于继承体系之下。它无法应用在缺乏虚函数的类型身上,也不能改变类型的常量性。②dynamic_cast的第二个用途是找出被某对象占用的内存的起始点。例如:classHeapTracked{public:boolisOnheap()const;private:typedefconstvoid*RawAddress;staticlistRawAddressaddresses;};boolHeapTracked::isOnheap()const{constvoid*rawAddress=dynamic_castconstvoid*(this);//取得一个指针,指向*this所占内存的起始处listRawAddress::iteratorit=find(addresses.begin(),addresses.end(),rawAddress);returnit!=addresses.end();}凡涉及”多重继承或虚拟基类“的对象,会拥有多个地址,只要简单地将指针”动态转型“为void*(或constvoid*或volatilevoid*或constvolatilevoid*),便会获得一个指针,指向”原指针所指对象“的内存起始处。不过,dynamic_cast只适用于那种”所指对象至少有一个虚函数“的指针身上。4)reinterpret_cast这个操作符的转换结果几乎总是与编译平台息息相关。所以reinterpret_cast不具移植性。reinterpret_cast的最常用用途是转换”函数指针“类型。假设有一个数组,存储的都是函数指针,有特定的类型:typedefvoid(*FuncPtr)();//FuncPtr是个指针,指向某个函数。FuncPtrfuncPtrArray[10];//funcPtrArray是个数组,内有10个FuncPtrs。假设由于某种原因,你希望将以下函数的一个指针放进funcPtrArray中:intdoSomething();如果没有转型,不可能办到这一点,因为doSomething的类型与funcPtrArray所能接受的不同。funcPtrArray内各函数指针所指函数的返回值是void,但doSomething的返回值却是int:funPtrArray[0]=&doSomething;//错误!类型不对使用reinterpret_cast,可以强迫编译器了解你的意图。funcPtrArray[0]=reinterpret_castFuncPtr(&doSomething);函数指针的转型动作并不具有移植性(C++不保证所有的函数指针都能以此方式重新呈现),某些情况下这样的转型可能会导致不正确的结果,所以应该尽量避免将函数指针转型。如果编译器尚未支持这些新式转型动作,也可以使用传统转型方式取代static_cast、const_cast和reinterpret_cast。甚至可以利用宏来仿真这些新语法。#definestatic_cast(TYPE,EXPR)((TYPE)(EXPR))#defineconst_cast(TYPE,EXPR)((TYPE)(EXPR))#definereinterpret_cast(TYPE,EXPR)((TYPE)(EXPR))至于dynamic_cast,也可回头使用旧式的C型语法,或者定义一个宏,但是它们不可能告诉你转型是否成功。
本文标题:C++中的四种转型操作符
链接地址:https://www.777doc.com/doc-2901581 .html