RTTI通过vtable和type_info实现运行时类型识别,dynamic_cast依赖虚函数表中的类型信息进行安全向下转型,typeid则获取对象实际类型并支持类型比较。

RTTI(Run-Time Type Information,运行时类型信息)是C++中用于在程序运行期间识别和操作对象类型的机制。它主要支持两种语言特性:dynamic_cast 和 typeid。这些功能依赖于编译器在编译期为多态类型(即包含虚函数的类)生成的额外类型信息,并在运行时由系统使用这些信息完成类型检查与转换。
dynamic_cast 的底层原理
dynamic_cast 用于安全地在继承层次中进行向下转型(downcasting),即将基类指针或引用转为派生类指针或引用。它只能用于多态类型(有虚函数的类),否则编译会报错。
其底层实现依赖于以下机制:
- 虚函数表(vtable)扩展:编译器为每个具有虚函数的类生成一个虚函数表,同时在其中或附加结构中加入指向 type_info 的指针,记录该类的类型信息。
- type_info 结构:每个类对应一个 std::type_info 对象,保存类名、继承关系等元数据。这些信息在编译时生成,运行时可访问。
- 运行时类型检查:当执行 dynamic_cast 时,系统通过对象的 vptr 找到 vtable,再获取 type_info,然后沿着继承链检查目标类型是否可达(例如是否是某个派生类)。
- 安全性保障:如果转换不合法,对于指针返回 nullptr,对于引用则抛出 std::bad_cast 异常。
例如:
立即学习“C++免费学习笔记(深入)”;
Base* ptr = new Derived();Derived* d = dynamic_cast
如果 ptr 实际指向的是另一个非 Derived 类型的对象,则结果为 nullptr。
typeid 的底层原理
typeid 用于在运行时获取对象的类型信息,返回一个 const std::type_info& 引用。
它的实现也基于 RTTI 系统:
- 依赖 vtable 中的 type_info 指针:当对一个多态类型的表达式使用 typeid(如 typeid(*ptr)),系统通过对象的 vptr 访问其实际类型的 type_info。
- 静态类型 vs 动态类型:若对象不是多态类型,typeid 返回的是表达式的静态类型;如果是多态类型且传入解引用指针(如 *ptr),则返回对象的实际运行时类型。
- type_info 的唯一性:同一个类的 typeid 总返回相同的 type_info 实例,可通过 == 或 != 比较类型是否相同。
示例:
Base* ptr = new Derived();std::cout
RTTI 的开销与限制
RTTI 虽然提供了运行时类型识别能力,但也有代价和使用限制:
- 性能开销:dynamic_cast 需要遍历继承树,尤其在深继承层级中可能较慢。
- 内存开销:每个带有虚函数的类都需要存储 type_info 指针,增加对象体积(间接通过 vtable)。
- 仅适用于多态类型:没有虚函数的类无法使用 dynamic_cast 或基于动态类型的 typeid。
- 可被禁用:某些编译器支持 -fno-rtti 选项关闭 RTTI,此时使用 dynamic_cast 或 typeid 会导致编译错误。
基本上就这些。RTTI 是 C++ 在保持效率的同时提供一定反射能力的折中设计,理解其背后依赖 vtable 和 type_info 的机制,有助于更合理地使用 dynamic_cast 和 typeid,避免误用或性能陷阱。










