typeid用于运行时类型查询,返回std::type_info引用;限制包括:仅多态类型支持动态类型识别、需启用RTTI、空指针解引用抛bad_typeid、跨编译单元比较不可靠、对数组/引用/CV限定符敏感。

typeid 在 C++ 里怎么用,有哪些限制
typeid 是 C++ 提供的运行时类型查询操作符,返回一个 std::type_info 引用,可用于获取对象或类型的静态/动态类型信息。但它不是万能的:对非多态类型(即不含虚函数的类),typeid 返回的是**编译期类型**,而非实际对象类型。
- 必须开启 RTTI 支持(大多数编译器默认开启;GCC/Clang 用
-frtti,MSVC 默认启用) - 对空指针调用
typeid(*ptr)会抛出std::bad_typeid异常 -
typeid不支持比较不同编译单元中定义的同名类(因type_info::name()可能不一致,且operator==的行为依赖实现) - 对数组、引用、cv 限定符敏感:
typeid(int[3])、typeid(const int&)都产生独立的type_info
RTTI 开启后,dynamic_cast 为什么比 static_cast 更安全
RTTI 的核心价值之一是支撑 dynamic_cast 的安全向下转型。它只对**多态类型**(含至少一个虚函数)生效,并在运行时检查继承关系是否成立。失败时,对指针返回 nullptr,对引用抛出 std::bad_cast。
-
static_cast在编译期完成转换,不验证实际对象类型,误转会导致未定义行为 -
dynamic_cast要求源类型必须是多态的;否则编译报错:error: cannot dynamic_cast ... which is not a polymorphic type - 多重继承下,
dynamic_cast还能正确调整this指针偏移,static_cast无法保证这点 - 性能开销存在:每次调用需查虚表中的 type_info 指针并做比较,但现代编译器对单继承有优化
如何判断一个类型是否支持 RTTI(即是否多态)
不能靠 typeid 或 dynamic_cast 是否“报错”来探测——它们的行为依赖编译选项和类型结构。最可靠的方式是在编译期用类型特征:
static_assert(std::is_polymorphic_v, "MyClass must be polymorphic for RTTI use");
-
std::is_polymorphic_v在中定义,返回true当且仅当T有虚函数(包括虚析构) - 注意:空基类、POD 类型、无虚函数的派生类都不满足该条件
- 即使开启了 RTTI,对非多态类型使用
dynamic_cast仍非法;而typeid虽可用,但结果与static_cast等效,无动态意义
常见 RTTI 相关错误和调试建议
RTTI 问题往往表现为静默错误或崩溃,而不是编译失败。典型现象包括:
立即学习“C++免费学习笔记(深入)”;
- 用
dynamic_cast转换非多态类型 → 编译失败,看清错误信息里的 “not a polymorphic type” - 对 null 指针解引用后
typeid→ 抛std::bad_typeid,应先判空 - 跨 DLL/so 边界传递对象并
typeid比较 →type_info::operator==可能返回 false,即使名字相同;避免跨模块直接比较type_info,改用字符串名(但注意name()无标准格式) - 关闭 RTTI(如 GCC 加
-fno-rtti)后仍用了dynamic_cast或typeid→ 链接失败或编译报错,错误提示通常明确
真正麻烦的是误以为 typeid 能替代接口设计:比如用一长串 if (typeid(obj) == typeid(A)) {...} else if (typeid(obj) == typeid(B))...。这不仅脆弱、难维护,还绕过了虚函数机制本应提供的扩展性。遇到这种代码,优先考虑重构为访问者模式或 std::variant(C++17)。










