基本技能12.8:类型转换运算符
C++中定义了五种类型转换运算符。其中的第一种就是我们在前面描述过的传统的类型转换。其余的四种类型转换运算符是前几年才加入到C++中。它们是:dynamic_cast, const_cast, reinterpret_cast和static_cast。这些运算符使得我们在进行类型转换的时候可以获得更多的控制权。下面逐一对其进行简单的介绍。
dynamic_cast
或许后来增加的这四种类型转换运算符中最重要的就是dynamic_cast(动态类型转)了。动态类型转换是在程序运行时的类型转换,并能对转换是否有效进行验证。如果在进行类型转换时发现转换是无效的,则动态类型转换会失败。其通用的形式如下:
dynamic_cast<目标类型>(表达式)
其中,目标类型就指定了转换后的类型;表达式就是需要转换的对象了。其中的目标类型必须是指针或者引用类型,并且表达式也必须是可以被评估为指针或者引用的表达式。因此,动态类型转换可以被用来把一种类型的指针转换为另外一种类型的指针,或者把这一种引用转换为另外一种类型的引用。
引入动态类型转换的目的是针对具有多态性的类的。假设有两个多态性的类B和D;D是从B继承而来的。动态类型转换总是能成功地把D类型的指针转换为B类型的指针。这是因为基类指针是可以指向任意的派生类的对象的。但是动态类型转换只有在B类的指针指向对象的实际类型是D类对象的时候才能把该B类指针转换为D类型的指针。通常,动态类型转换在被转换指针指向的是目标类型的对象或者是目标类型的派生类的对象时才能转换成功;在其它情况下转换都会失败。在转换失败的情况下,如果是进行指针类型的转换,那么转换的值就是null;如果进行的是引用类型的转换,则会抛出bad_cast异常。
下面是一个简单的例子。假定Base是具有多态性的类;而Berived是从Base派生而来的类。
Base* bp, b_ob;
Derived * dp, d_ob;
bp = &d_ob; //基类指针指向派生类的对象
dp = dynamic_cast<Derived *> (bp)'//将基类的指针转换为派生类的指针
if(dp) cout << "Cast OK"
在这段代码中,由于基类指针bp指向对象的是派生类的对象,因此从基类指针到派生类指针的转换是成功的。因此,上述代码片段将显示CastOK。但是在下面的代码片段中,由于bp指向的是基类对象,把基类对象转换为派生类对象是不合法的,因此类型转换会失败。
bp = &b_ob; //基类指针指向派生类的对象
dp = dynamic_cast<Derived *> (bp);//将基类的指针转换为派生类的指针
if (!dp) cout << "Cast Fails";
由于转换失败了,所以会输出Cast Fails。
const_cast
const_cast是用来对常量或者易变量进行类型转换的。其目标类型和源类型除了const或者volatiole属性可以不一样外,其类型一样的。const_cast最常用的就是用来移除const属性。其通用的形式如下:
const_cast<类型>(表达式)
其中的类型就是指定的目标类型;表达式就是需要对其进行类型转换的表达式。必须强调的是使用const_cast来去除常量属性很有可能存在潜在的危险,因此在使用的时候需要格外的注意。
还有一点需要注意:只有const_cast能够移除对象的const属性。也就是说dynamic_cast,static_cast和reinterpret_case都不能修改对象的const属性的。
static_cast
静态类型转换进行的是非多态性的转换。它可用于任意的标准转换,也不会进行运行时检查。因此,静态类型转换实质上是传统的类型转换的替代方式。其通用形式如下:
static_cast<目标类型>(表达式)
其中的目标类型就表明了转换的目的类型;表达式就是需要对其转换的表达式。
reinterpret_cast
这个运算符把一种类型转换为另外一种从本质上完全不同的类型。例如,把指针转换为整型数或者把整型数转换为指针。它还可以被用来就继承关系上来说不兼容得指针类型的转换。其通用形式如下:
reinterpret_cast<目标类型>(表达式)
其中的目标类型就指明了转换的目的类型;表达式就是需要对其类型转换的表达式。