typeid仅对多态类有效,需虚函数支持;非多态类、空指针解引用或关闭RTTI时失效;typeid(*ptr)返回动态类型,typeid(ptr)返回指针静态类型;type_info::name()不可读且不跨平台,应优先用hash_code()或==比较。

typeid 能在运行时拿到对象真实类型,但只对多态类(含虚函数)有效;非多态类型、空指针解引用、关闭 RTTI 时都会失效或抛 std::bad_typeid。
typeid(*ptr) 返回动态类型,但前提是类必须有虚函数
当你用 Base* 指向 Derived 对象时,typeid(*ptr) 只有在 Base 类至少有一个虚函数(比如虚析构函数)的前提下,才返回 Derived 的实际类型;否则它退化为静态类型,即始终返回 Base。
- 常见错误:删掉
virtual ~Base() {}后,typeid(*ptr).name()输出和typeid(Base).name()完全一致 - 检查是否多态:可用
std::is_polymorphic_v在编译期验证 - MSVC 默认启用 RTTI,但若显式加了
/GR-,typeid将直接报错或返回空信息 - GCC/Clang 需确保没用
-fno-rtti,否则typeid行为未定义
typeid(expr) 和 typeid(*ptr) 的区别必须分清
typeid 作用对象不同,结果完全不同:
-
typeid(ptr)→ 拿的是指针变量自身的类型,比如Base*,和它指向谁无关 -
typeid(*ptr)→ 才可能触发动态类型查询,但仅当ptr非空且所指对象类型是多态的 -
typeid(nullptr)合法,但typeid(*nullptr)会立即抛std::bad_typeid - 对引用同理:
typeid(ref)等价于typeid(*ptr),不是引用声明类型
type_info::name() 返回值不可读,别直接用于日志或用户界面
std::type_info::name() 返回的是编译器内部 mangling 后的字符串,例如 GCC 下 int 是 i,std::vector 可能是 St6vectorIiSaIiEE —— 它不是稳定 ABI,也不可跨平台解析。
- 调试时可用
abi::__cxa_demangle(GCC/Clang)尝试还原,但需手动处理内存和异常 - MSVC 下可用
__unDName,但同样不保证 100% 成功 - 生产环境建议用
type_info::hash_code()做类型判等,比name()更可靠 - 若需可读名,应在类中显式提供
static constexpr const char* type_name() { return "Derived"; }
用 == 比较 typeid 结果比 strcmp(name()) 更安全
直接比较 typeid(a) == typeid(b) 是标准支持的、类型安全的方式;而用 strcmp(typeid(a).name(), typeid(b).name()) == 0 既不可靠(mangled 名可能重复),又不处理 const/volatile 修饰差异。
-
typeid(a) == typeid(const A&)返回 true,但name()可能不同 - 对模板实例化类型,
hash_code()可用于无符号整数哈希表索引,避免字符串开销 - 注意:两个
type_info对象的==比较,只要类型相同就返回 true,不依赖name()内容
真正容易被忽略的是:RTTI 不是免费的。每个含虚函数的类对象会增加虚表指针开销,typeid 查询本身也有间接跳转成本;在嵌入式或高频调用路径中,应优先用编译期类型特征(如 std::is_same_v)或手动类型标签替代。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










