RTTI与typeid运算符的实现原理
C++中RTTI(Run-Time Type Information)是如何实现的?typeid运算符如何获取对象的动态类型?它在底层依赖什么数据结构(type_info/vtable指针)?什么情况下typeid会抛异常?
回答
孤独的心
实现原理:RTTI依赖于vtable指针(vptr)——每个多态类(含虚函数的类)的虚表中包含一个指向type_info对象的指针。当调用typeid(*ptr)时:
- 通过对象的vptr找到vtable
- 从vtable中的固定偏移获取
type_info* - 返回
std::type_info的引用
type_info结构:包含类型名称字符串(由编译器生成,可用于比较operator==/before(字典序比较))。不同编译器名称修饰(name mangling)规则不同,但同一编译器内是唯一的。
typeid使用规则:
Base* pb = new Derived();
const std::type_info& ti = typeid(*pb); // RTTI:返回Derived的type_info
typeid(Base) // 编译期:返回Base的type_info(静态类型)
typeid(pb) // 返回Base*(指针)的type_info,不是多态
抛异常情况:当typeid的操作数是对空指针解引用的表达式时:
Base* p = nullptr;
typeid(*p); // 抛出std::bad_typeid异常
但如果typeid(p)(对指针本身,不是解引用)不会抛异常。
性能开销:typeid需要运行时指针间接访问(RTTI查找),比静态类型检查慢。typeid比较需要在运行时通过vtable的type_info指针对比。
禁用RTTI:编译选项-fno-rtti(GCC/Clang)或/GR-(MSVC)可关闭RTTI生成,节省vtable空间和二进制大小,但typeid/dynamic_cast将不可用。