RTTI简介
RTTI(Runtime Type Identification)是"运行时类型识别"的意思。C++是一门静态类型语言,其数据类型是在编译期就确定的,不能在运行时更改。然而由于面向对象程序设计中多态性的要求,C++中的指针或引用本身的类型,可能与它实际代表的类型并不一致,有时我们需要将一个多态指针转换为其实际指向对象的类型,就需要知道运行时的类型信息,这就有了运行时类型识别需求。和Java相比,C++要想获得运行时类型信息,只能通过RTTI机制,并且C++最终生成的代码是直接与机器相关的。
C++通过以下两个关键字提供RTTI功能:
- typeid:该运算符返回其表达式或类型名的实际类型
- dynamic_cast:该运算符将基类的指针或引用安全地转换为派生类类型的指针或引用(也就是所谓的下行转换)
typeid
静态
当typeid中的操作数是以下任意一种时,typeid得出的是静态类型,即编译时就确定的类型:
- 一个任意的类型名
- 一个基本内置类型的变量,或指向基本内置类型的指针或引用
- 一个任意类型的指针(指针就是指针,本身不体现多态,多指针解引用才有可能会体现多态)
- 一个具体的对象实例,无论对应的类有没有多态都可以直接在编译器确定
- 一个指向没有多态的类对象的指针的解引用
- 一个指向没有多态的类对象的引用
动态
当typeid
中的操作数是以下任意一种时,typeid
需要在程序运行时推算类型,因为其操作数的类型在编译时期是不能被确定的:
- 一个指向含有多态的类对象的指针的解引用
- 一个指向含有多态的类对象的引用
dynamic_cast
这是最常用的RTTI组件,它不能回答"指针指向的是哪类对象"这样的问题,但能够回答"是否可以安全地将对象的地址赋给特定类型的指针"这样的问题。
说白了,就是看看这个对象指针能不能转换为目标指针。
通常,如果指向的对象(*pt
)的类型为Type或者是从Type直接或简介派生而来的类型,则下面的表达式将指针pt
转换为Type类型的指针:
cpp
dynamic_cast<Type *>(pt)
否则,结果为0,即空指针。
注意:即使编译器支持RTTI,在默认情况下,它也可能关闭该特性。如果该特性被关闭,程序可能仍能够通过编译,但将出现运行阶段错误。在这种情况下,应该查看文档或菜单选项。
也可以将dynamic_cast
用于引用,用法稍微有点不同:
没有与空指针对应的引用值,因此无法使用特殊的引用值来指示失败。当请求不正确时,dynamic_cast
将引发类型为bad_cast
的异常,这种异常是从exception
类派生而来的,它是在头文件typeinfo中定义的。