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
不是所有使用 typeid 或 dynamic_cast 的代码都会“编译失败”,但行为会退化或崩溃:
-fno-rtti 后:dynamic_cast 对多态类型的指针转将始终返回 nullptr(即使本该成功);引用转型会调用 __dynamic_cast 符号,链接失败typeid 表达式仍能编译,但对多态对象返回的是静态类型(即忽略虚表),失去运行时识别能力#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,这部分内存和间接访问成本就已存在。