c++ rtti 依赖编译器开启(如 gcc/clang 默认开,可用 -fno-rtti 关闭;msvc 用 /gr-),typeid 和 dynamic_cast 仅对多态类型有效,禁用后二者编译失败;typeid::name() 返回不可读内部名,需 demangle 或用 hash_code/== 比较;dynamic_cast 仅支持安全向下转型,性能低于 static_cast;深度反射需第三方库或自定义方案。

运行时获取类型信息在 C++ 中依赖 RTTI(Run-Time Type Information),但它的能力有限,且默认开启但可被禁用——你得先确认编译器没关掉它,否则 typeid 和 dynamic_cast 会失效或行为异常。
怎么安全使用 typeid 获取类型名
typeid 返回 std::type_info 引用,但 type_info::name() 返回的是未修饰的、编译器相关的内部字符串(比如 "St6vectorIiSaIiEE"),不能直接用于比较或日志;需配合 type_info::hash_code() 或 == 运算符做类型判等。
- 对多态类型(含虚函数的类),
typeid返回实际动态类型;对非多态类型,只返回静态声明类型 - 不要对空指针用
typeid(*ptr),会抛std::bad_typeid - 若需可读名,Linux/macOS 可用
abi::__cxa_demangle解析name(),Windows 用UnDecorateSymbolName;但这是平台相关操作,不是标准 C++ 行为
dynamic_cast 是唯一能跨继承树安全转型的机制
它只对多态类型(即至少有一个虚函数的类)有效,且要求开启 RTTI。转换失败时,对指针返回 nullptr,对引用抛 std::bad_cast。
- 向下转型(基类指针 → 派生类指针):必须确保对象真实类型兼容,否则返回空
- 向上转型(派生 → 基类)不需要
dynamic_cast,隐式转换即可 - 横向转型(同级派生类之间)不合法,编译不过
- 性能开销比
static_cast明显,因需遍历虚函数表中的 typeinfo 结构
RTTI 被禁用时会发生什么
Clang/GCC 用 -fno-rtti、MSVC 用 /GR- 关闭 RTTI 后:typeid 表达式编译失败(除非作用于非类类型如 int),dynamic_cast 编译报错(“cannot use dynamic_cast with -fno-rtti”)。
立即学习“C++免费学习笔记(深入)”;
- 常见于嵌入式或游戏引擎底层模块,此时只能靠自定义类型 ID(如枚举 +
virtual GetTypeID())模拟运行时类型查询 - 某些反射框架(如 refl-cpp、magic_enum)也不依赖 RTTI,而是基于编译期字符串字面量或宏展开生成类型映射
- 关闭 RTTI 后,
std::any和std::variant仍可用,但它们内部不依赖typeid,而是用其他机制做类型擦除和访问校验
RTTI 的核心限制在于:它只告诉你“是不是某个类型”,不提供成员、函数、模板参数等完整元信息;真要深度反射,得接受额外构建步骤或放弃纯标准 C++ 方案。










