在std::type_info映射中,能否通过父类B的type_info获取子类C实例?
关于std::type_info、继承与std::map的使用问题
首先要指出你代码里的一个关键错误:std::type_info不能直接作为std::map的键。原因有两点:
- std::type_info的拷贝构造函数是被删除的,无法被复制,而std::map要求键类型必须支持拷贝;
- 标准没有为std::type_info定义
operator<,虽然部分编译器可能提供非标准实现,但这是不可移植的。
正确的做法是使用<typeindex>头中的std::type_index,它包装了std::type_info*,并且提供了合法的比较运算符,完全符合容器键的要求,你的映射应该定义为:
std::map<std::type_index, std::shared_ptr<A>> m_map;
接下来回答你的核心问题:即使修正了键类型,用m_map.find(std::type_index(typeid(B)))也无法获取map中的C类实例。
原因在于typeid的行为:
typeid(B)返回的是对应抽象类B的std::type_info对象;- 而C类实例对应的
type_info是typeid(C),两者是完全不同的对象,std::type_index对它们的比较结果是不相等的。typeid的匹配是严格的类型匹配,不会考虑继承关系——它只会返回对象的实际类型(多态场景下)或指定的静态类型。
如果你的需求是查找所有继承自B的类型实例,不能通过键直接查找,可行的方案是:
- 遍历整个map,对每个
std::shared_ptr<A>,尝试用dynamic_cast<B*>转换:如果转换成功,说明该实例是B或B的派生类(比如C)的对象;std::vector<std::shared_ptr<A>> find_all_B_derived() { std::vector<std::shared_ptr<A>> result; for (const auto& pair : m_map) { if (dynamic_cast<B*>(pair.second.get())) { result.push_back(pair.second); } } return result; } - 或者在插入实例时,额外维护一个按基类分组的结构(比如
std::unordered_map<std::type_index, std::vector<std::shared_ptr<A>>>),但这需要提前明确需要支持的基类,且要处理类型体系的扩展问题。
总结:
- 不能用
std::type_info作为std::map的键,必须用std::type_index; - 严格的类型键无法通过基类类型查找派生类实例,需要通过动态类型检查或额外的结构来实现需求。
内容的提问来源于stack exchange,提问作者Theofanis kouniakis
相关产品推荐
相关产品推荐

