通过RTTI,能够通过基类的指针或引用来检索其所指对象的实际类型。c++通过下面两个操作符提供RTTI。
-
typeid:返回指针或引用所指对象的实际类型。
-
dynamic_cast:将基类类型的指针或引用安全的转换为派生类型的指针或引用。
对于带虚函数的类,在运行时执行RTTI操作符,返回动态类型信息;对于其他类型,在编译时执行RTTI,返回静态类型信息。
当具有基类的指针或引用,但需要执行派生类操作时,需要动态的强制类型转换(dynamic_cast)。这种机制的使用容易出错,最好以虚函数机制代替之。
dynamic_cast 操作符
如果dynamic_cast转换指针类型失败,则返回0;如果转换引用类型失败,则抛出一个bad_cast类型的异常。
可以对值为0的指针使用dynamic_cast,结果为0。
dynamic_cast会首先验证转换是否有效,只有转换有效,操作符才进行实际的转换
if (Derived *derivedPtr = dynamic_cast<Derived *>(basePtr))
{
// use the Derived object to which derivedPtr points
}
else
{
// basePtr points at a Base object
// use the Base object to which basePtr points
}
也可以使用dynamic_cast将基类引用转换为派生类引用:dynamic_cast<Type&>(val)
因为不存在空引用,所以不能像指针一样对转换结果进行判断。不过转换引用类型失败时,会抛出std::bad_cast异常。
try
{
const Derived &d = dynamic_cast<const Derived&>(b);
}
catch (bad_cast) {
// handle the fact that the cast failed.
}
typeid操作符
typeid能够获取一个表达式的类型:typeid(e)。
如果操作数不是类类型或者是没有虚函数的类,则获取其静态类型;如果操作数是定义了虚函数的类类型,则计算运行时类型。
typeid最常见的用途是比较两个表达式的类型,或者将表达式的类型与特定类型相比较。
获取方法:
type_info:通过typeid,返回一个type_info
注意:不要将typeid作用于指针,应该作用于引用,或解引用的指针(实现多态的判断)
#include <iostream>
#include <string>
using namespace std;
class Test{
public:
virtual void print() = 0;
};
class TestA : public Test{
public:
virtual void print(){