typeid不能安全用于未定义行为表达式或非多态类型地址比较;应优先用dynamic_cast替代,因其更安全、语义清晰且支持空指针检查。
typeid 不能安全用于未定义行为的表达式,也不能在非多态类型上可靠比较地址 —— 这是 RTTI 最常被误用的两个起点。
它返回 std::type_info 引用,但该对象不保证生命周期长于表达式求值;对临时对象或未求值表达式(如 typeid(int))可用,但对运行时多态对象必须确保对象有效。
typeid(obj) 返回编译期类型,不依赖实际对象内容typeid(*ptr) 才会触发动态类型查询;若 ptr 为空或指向已析构对象,行为未定义typeid 不支持比较不同编译单元中同名类型的 type_info 地址(可能重复实例化)直接用 == 比较 typeid 结果看似简洁,但有陷阱:跨 DLL/so 时 type_info::name() 可能相同而地址不同,且 name() 不可移植(各编译器格式不同)。
class Base { virtual ~Base() = default; };
class Derived : public Base {};
Base ptr = new Derived();
if (typeid(ptr) == typeid(Derived)) { / 安全,因为 ptr 非空且多态 / }
// 危险示例:
Base bad_ptr = nullptr;
typeid(bad_ptr); // 未定义行为
当目标是“判断能否转为某类型”时,dynamic_cast 比 typeid 更直观、更安全,且明确表达了意图。
dynamic_cast(ptr) 返回非空指针表示成功,比字符串比对或地址比对更符合语义-fno-rtti 下 typeid 被禁用,但 dynamic_cast 同样失效)
对引用类型抛异常,需 try/catch;指针版本则只返回 nullptr,推荐优先使用if (auto d = dynamic_cast(ptr)) { // 安全调用 Derived 特有接口 }
启用 RTTI(默认开启)会为每个含虚函数的类生成 type_info 全局对象,并在虚表末尾附加类型信息指针。禁用(-fno-rtti)后:typeid 和 dynamic_cast 均不可用,链接时报错。
typeid(T).hash_code() 是稳定哈希值,可用于 std::unordered_map 键,比 name() 可靠真正难处理的是跨模块类型识别 —— 此时连 hash_code() 都可能不一致,只能靠接口抽象或手动注册类型 ID。