第18章 特殊工具与技术(6)
18.2 运行时类型识别
通过运行时类型识别(RTTI),程序能够使用基类的指针或引用来检索这些指针或引用所指对象的实际派生类型。
通过下面两个操作符提供RTTI:
(1) typeid操作符,返回指针或引用所指对象的实际类型。
(2) dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用。
这些操作符只为带有一个或多个虚函数的类返回动态类型信息,对于其他类型,返回静态(即编译时)类型的信息。
对于带虚函数的类,在运行时执行RTTI操作符,但对于其他类型,在编译时计算RTTI操作符。
从基类指针获得派生类型为最好的方法是通过虚函数。当使用虚函数的时候,编译器自动根据对象的实际类型选择正确的函数。
使用动态强制类型转换要小心。只要有可能,定义和使用虚函数比直接接管类型管理好得多。
18.2.1 dynamic_cast操作符
可以使用dynamic_cast操作符将基类类型对象的引用或指针转换为同一继承层次中其他类型的引用或指针。与dynamic_cast一起使用的指针必须是有效的——它必须为0或者指向一个对象。
与其他强制类型转换不同,dynamic_cast涉及运行时类型检查。如果绑定到引用或指针的对象不是目标类型对象,则dynamic_cast失败。如果转换到指针类型的dynamic_cast失败,则dynamic_cast的结果是0值;如果转换到引用类型的dynamic_cast失败,则抛出一个bad_cast类型的异常。
因此,dynamic_cast操作符一次执行两个操作。它首先验证被请求的转换是否有效,只有转换有效,操作符才实际进行转换。一般而言,引用或指针所绑定的对象的类型在编译时是未知的,基类的指针可以赋值为指向派生类对象,同样,基类的引用也可以用派生类对象初始化,因此,dynamic_cast操作符执行的验证必须在运行时进行。
1. 使用dynamic_cast操作符
可以对值为0的指针应用dynamic_cast,这样做的结果是0。
继承不代表有多态性,继承只是多态性的一个前提条件。
dynamic_cast需要具有多态性的类才能进行转换。virtual function是保证多态性的条件。
如果没有virtual,即使是有继承关系的类型之间,也不能使用dynamic_cast进行转换。VS报出的编译错误很直接的:type is not polymorphic
Base1 *ba=new Child1();
Child1 *c=dynamic_cast<Child1*>(ba);
Base1 *ba=new Child1();
Child1 *c=dynamic_cast<Child1*>(ba); class Base1{
public:
virtual void Method1(){}
};
class Child1:public Base1{
public:
virtual void Method1(){}
};
class Base1{
public:
virtual void Method1(){}
};
class Child1:public Base1{
public:
virtual void Method1(){}
};2. 使用dynamic_cast和引用类型
也可以使用dynamic_cast将基类引用转换为派生类引用。
因为不存在空引用,所以不可能使用用于指针强制类型转换的检查策略,相反,当转换失败的时候,它抛出一个std::bad_cast异常,该异常在库头文件typeinfo中定义。
Child1 ba=Child1();
Base1 &b=ba;
try{
Child1 &c=dynamic_cast<Child1&>(b);
}
catch(bad_cast){
}
摘自 xufei96的专栏
补充:软件开发 , C++ ,