在计算机编程中,运行时类型信息(Runtime Type Information,简称RTTI)或运行时类型标识(Runtime Type Identification)是某些编程语言(如C++、Object Pascal、Ada)的一个特性,它允许在程序运行时获取对象的数据类型信息。RTTI可以用于所有类型,也只能用于显式启用RTTI的类型(如Ada)。RTTI是更一般的类型内省(Type Introspection)概念的一种专门化。
在最初的C++设计中,Bjarne Stroustrup并未包含RTTI功能,因为他认为这种机制经常被滥用。
概述
在C++中,RTTI可以通过dynamic_cast<>
运算符进行安全的类型转换,并可以通过typeid
运算符和std::type_info
类在运行时操作类型信息。在Object Pascal中,RTTI可以通过as
运算符进行安全的类型转换,使用is
运算符测试对象所属的类,并利用RTTI单元中的类在运行时操作类型信息(如:TRttiContext
、TRttiInstanceType
等类)。在Ada中,带标签的类型对象也存储类型标签,这允许在运行时识别这些对象的类型。in
运算符可以在运行时测试对象是否属于特定类型并安全地转换。
RTTI仅适用于多态类,即包含至少一个虚方法的类。在实践中,这并不构成限制,因为基类必须具有虚析构函数,以便从基类指针删除派生类对象时可以执行正确的清理操作。
一些编译器具有禁用RTTI的标志。使用这些标志可以减小应用程序的整体大小,特别适合内存有限的系统。
C++中的typeid
typeid
关键字用于在运行时确定对象的类。它返回对std::type_info
对象的引用,该对象在程序结束前一直存在。与在只需类信息的情况下使用dynamic_cast<class_type>
不同,typeid
始终是一个常时间操作,而dynamic_cast
可能需要在运行时遍历其参数的类继承结构。返回对象的某些方面是实现定义的,例如std::type_info::name()
,跨编译器可能不一致。
当typeid
表达式通过对空指针应用一元*
运算符时,会抛出std::bad_typeid
类对象。对于其他空引用参数是否抛出异常是实现依赖的。换言之,保证抛出异常的表达式形式必须是typeid(*p)
,其中p
是任何导致空指针的表达式。
示例
#include <iostream>
#include <typeinfo>
class Person {
public:
virtual ~Person() = default;
};
class Employee : public Person {
};
int main() {
Person person;
Employee employee;
Person* ptr = &employee;
Person& ref = employee;
std::cout << typeid(person).name()