贝利信息

c++中如何使用typeid获取类型信息_c++ RTTI机制详解

日期:2026-01-07 00:00 / 作者:尼克
typeid不能安全用于未定义行为表达式或非多态类型地址比较;应优先用dynamic_cast替代,因其更安全、语义清晰且支持空指针检查。

typeid 不能安全用于未定义行为的表达式,也不能在非多态类型上可靠比较地址 —— 这是 RTTI 最常被误用的两个起点。

typeid 的基本用法和限制

它返回 std::type_info 引用,但该对象不保证生命周期长于表达式求值;对临时对象或未求值表达式(如 typeid(int))可用,但对运行时多态对象必须确保对象有效。

如何安全比较两个对象的动态类型

直接用 == 比较 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 + nullptr 检查更可靠

当目标是“判断能否转为某类型”时,dynamic_cast typeid 更直观、更安全,且明确表达了意图。

if (auto d = dynamic_cast(ptr)) {
    // 安全调用 Derived 特有接口
}

RTTI 性能与编译选项影响

启用 RTTI(默认开启)会为每个含虚函数的类生成 type_info 全局对象,并在虚表末尾附加类型信息指针。禁用(-fno-rtti)后:typeiddynamic_cast 均不可用,链接时报错。

真正难处理的是跨模块类型识别 —— 此时连 hash_code() 都可能不一致,只能靠接口抽象或手动注册类型 ID。