typeid用于获取对象运行时实际类型(动态类型),仅当对象为多态类型(含虚函数)且对指针解引用(*ptr)或引用取类型时生效;否则返回静态类型。

它能告诉你一个对象在运行时“到底是什么类型”,尤其当你手头只有基类指针或引用,却需要确认它实际指向哪个派生类时——typeid 是少数几个能可靠回答这个问题的工具之一。
什么时候typeid返回的是动态类型?
只有一种情况:表达式涉及多态类型(即类至少有一个虚函数),且你对指针解引用或对引用取类型信息。
-
typeid(ptr)→ 返回指针本身的静态类型(比如Base*) -
typeid(*ptr)→ 返回ptr实际指向的对象的动态类型(比如Derived) -
typeid(obj_ref)→ 同样返回引用所绑定对象的动态类型 - 如果类没有虚函数,哪怕
*ptr指向派生对象,typeid(*ptr)仍只返回Base(静态类型)
typeid(expr).name() 输出乱码怎么办?
它返回的是编译器内部修饰名(如 St6vectorIiSaIiEE),不是可读字符串。别直接打印,更别拿它做字符串比较。
- 用
abi::__cxa_demangle(GCC/Clang)解码:char* demangled = abi::__cxa_demangle(typeid(x).name(), nullptr, nullptr, &status); - MSVC 下可用
__unDName,但更推荐统一用hash_code()做类型判等 - 真正可靠的比较方式是:
typeid(a) == typeid(b),而不是strcmp(typeid(a).name(), typeid(b).name()) == 0
空指针传给typeid(*ptr)会怎样?
直接抛出 std::bad_typeid 异常——这是最容易被忽略的崩溃点。
立即学习“C++免费学习笔记(深入)”;
- 只要写
typeid(*ptr),就必须先确保ptr != nullptr -
typeid(ptr)安全,因为它只看指针类型,不访问内存 - 若不确定指针有效性,改用
dynamic_cast更稳妥(失败返回nullptr,不抛异常) - RTTI 必须启用:GCC/Clang 默认开启;MSVC 需确认未禁用
/GR-
最常被低估的一点:你几乎从不需要把 typeid 当作“调试日志工具”来用。它的真正价值在于类型分发逻辑(比如容器中混合存储不同派生类对象后,按实际类型做不同序列化),而这类场景里,hash_code() 比 name() 更快更安全,operator== 比字符串比较更健壮。


















