C++中的RTTI(运行时类型识别)是什么?(typeid与dynamic_cast的支撑)

16次阅读

RTTI是c++运行时识别对象真实类型的必要机制,为typeid和dynamic_cast提供底层支持;禁用后dynamic_cast失效、typeid退化为静态类型识别,且虚函数类虚表恒含类型信息开销。

C++中的RTTI(运行时类型识别)是什么?(typeid与dynamic_cast的支撑)

RTTI 是 C++ 在运行时识别对象真实类型的机制,它不是可选的“功能开关”,而是 typeiddynamic_cast 能正常工作的底层保障——只要用了这两个操作符,编译器就默认启用了 RTTI(除非你显式禁用)。

为什么 typeid 有时返回 type_info 名字乱码或不一致?

因为 typeid 返回的是实现定义的 std::type_info::name() 字符串,未要求可读;不同编译器(如 GCC、Clang、MSVC)编码方式不同,常见为 mangling 后的符号名。

  • abi::__cxa_demangle(GCC/Clang)或 UnDecorateSymbolName(MSVC)解码才能看到可读名
  • 比较类型应始终用 typeid(a) == typeid(b),而非字符串比较
  • typeid 对纯右值(如临时对象)可能返回其静态类型,而非动态类型;要确保传入的是多态对象的引用或指针

dynamic_cast 失败时返回 nullptr 还是抛异常?

取决于目标类型:对指针类型转换失败返回 nullptr;对引用类型转换失败则抛出 std::bad_cast 异常。

  • 必须作用于多态类型(即至少含一个虚函数),否则编译报错:Error: cannot dynamic_cast ... (source type is not polymorphic)
  • 空指针参与 dynamic_cast 永远安全,结果仍是 nullptr
  • 向下转型(基类 → 派生类)才真正依赖 RTTI;向上转型(派生类 → 基类)是静态的,不需要 RTTI

禁用 RTTI 后哪些代码会直接失效?

不是所有使用 typeiddynamic_cast 的代码都会“编译失败”,但行为会退化或崩溃:

立即学习C++免费学习笔记(深入)”;

  • GCC/Clang 加 -fno-rtti 后:dynamic_cast 对多态类型的指针转将始终返回 nullptr(即使本该成功);引用转型会调用 __dynamic_cast 符号,链接失败
  • typeid 表达式仍能编译,但对多态对象返回的是静态类型(即忽略虚表),失去运行时识别能力
  • 第三方库如 Boost.TypeErasure、某些序列化框架若隐式依赖 RTTI,可能静默出错
#include  #include 

struct Base { virtual ~Base() = default; }; // 多态基类 struct Derived : Base {};

int main() { Base p = new Derived; std::cout << typeid(p).name() << "n"; // 依赖 RTTI,输出可能为 "7Derived" 或类似 Derived d = dynamic_cast>(p); // 依赖 RTTI,禁用后恒为 nullptr delete p; }

真正容易被忽略的是:RTTI 的开销不在“是否启用”,而在虚表中额外存储了类型信息指针;只要类有虚函数,即使从不写 typeiddynamic_cast,这部分内存和间接访问成本就已存在。

text=ZqhQzanResources