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

RTTI 是 C++ 在运行时识别对象真实类型的机制,它不是可选的“功能开关”,而是 typeid 和 dynamic_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 后哪些代码会直接失效?
不是所有使用 typeid 或 dynamic_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 的开销不在“是否启用”,而在虚表中额外存储了类型信息指针;只要类有虚函数,即使从不写 typeid 或 dynamic_cast,这部分内存和间接访问成本就已存在。










