std::type_index{typeid(ptr)}查不到派生类类型,因为typeid作用于指针变量返回的是指针静态类型(如Base),而非所指对象的动态类型;必须解引用(typeid(ptr))且Base为多态类、RTTI开启,才能正确识别实际类型。

std::type_index 本身不处理多态,它只是安全包装 typeid 的结果;真正做多态识别,得靠 typeid(*ptr) 或 typeid(obj),而不是 typeid(ptr)。
为什么 std::type_index{typeid(ptr)} 查不到派生类类型
常见错误现象:std::type_index{typeid(base_ptr)} 总是返回基类的 std::type_index,哪怕 base_ptr 实际指向派生对象
- 因为
typeid作用于指针变量时,返回的是指针类型(如Base*)本身,不是它所指对象的动态类型 - 要获取运行时实际类型,必须解引用:用
typeid(*base_ptr)(前提是base_ptr非空且Base有虚函数) - 或者传引用:
typeid(static_cast<const base>(*base_ptr))</const>更稳妥,避免空指针解引用 - RTTI 必须开启(GCC/Clang 默认开,MSVC 默认开;但嵌入式项目常加
-fno-rtti,此时typeid行为未定义)
std::unordered_map<:type_index t> 编译失败怎么办
错误信息:error: use of deleted function 'std::hash<:type_index>::hash()'</:type_index> 或类似提示
- C++11 起标准已特化
std::hash<:type_index></:type_index>,但部分旧编译器(如 GCC - 解决方法:显式提供哈希器,例如
std::unordered_map<:type_index t std::hash>></:type_index> - 更兼容写法:用
std::map替代——std::type_index支持operator(基于 <code>std::type_info::before()),无需额外配置 - 别自己手写哈希函数,
std::type_index::hash_code()值不稳定,不能跨次运行复用
注册和查询类型必须用一致的 cv 限定与值类别
常见错误现象:注册了 std::type_index{typeid(Widget)},却用 std::type_index{typeid(const Widget&)} 去查,结果 find() 返回 end()
立即学习“C++免费学习笔记(深入)”;
-
std::type_index完全忠实于typeid的语义:修饰符敏感,int、const int、int&、const int&全是不同键 - 统一约定:注册一律用“裸类型”(如
typeid(MyClass)),查询也用同种表达式;不要混用typeid(obj)和typeid(decltype(obj)) - 模板内慎用
typeid(T):若T是引用或 cv 限定类型,会带修饰符;建议用typeid(std::decay_t<t>{})</t>或明确构造值对象 - 对智能指针,
typeid(std::shared_ptr<base>)≠typeid(std::shared_ptr<derived>)</derived>,它们是不同模板实例化
std::type_index 不能替代 dynamic_cast,但能优化 dispatch 路径
典型误用:试图用 std::type_index 绕过虚函数调用或替代 dynamic_cast 安全性检查
-
std::type_index只做类型标识,不提供向下转型能力;拿到匹配键后仍需dynamic_cast或其他机制取具体对象 - 适合场景:事件分发、工厂创建、序列化器选择——即“先查类型再决定行为”,而非“查类型后强制转换”
- 性能上无负担:
std::type_index构造和比较都是 O(1),内部只存 conststd::type_info*;但反复调用typeid仍有少量开销,建议缓存 - 最易被忽略的一点:前置声明类不能用于
typeid,否则编译失败;所有注册类型必须有完整定义(class Widget;不够,得class Widget { ... };)


















