C++如何在std::map中存储泛型基类的模板派生类实例
问题根因
- 直接使用
std::map<std::string, generic>值存储的方案会触发对象切片:存入容器时派生类对象会被构造为基类实例,派生类持有的特化数据、重写的虚函数表指针都会丢失,访问时只能拿到基类行为,你的判断完全正确。 - 裸指针存储的方案存在生命周期管理缺陷:无论是栈上局部变量取地址存入容器,还是函数内局部变量取地址存入,变量离开作用域后指针就会成为悬垂指针,访问属于未定义行为。
- 你写的智能指针版本编译失败的核心原因:
add_item函数中遍历map时使用了值遍历for (auto i : m),这会尝试拷贝map中的元素,而std::unique_ptr是独占所有权的智能指针,拷贝构造/拷贝赋值函数被明确禁用,因此触发“use of deleted function”编译错误。
正确实现方案
使用std::unique_ptr<generic>作为map的值类型自动管理对象生命周期,遍历智能指针容器时使用引用遍历避免拷贝,即可实现无内存泄漏、无悬垂指针、保留完整多态行为的存储逻辑。
修正后的完整可运行代码:
#include <iostream> #include <string> #include <memory> #include <map> #include <typeinfo> class generic { std::string _name; public: generic(std::string name) : _name(std::move(name)) {} // 多态场景下基类必须定义虚析构,否则通过基类指针销毁派生类对象会触发未定义行为 virtual ~generic() = default; virtual std::string name() { return _name; } virtual std::string value() { return "no value in generic"; } }; template <class T> class special : public generic { T _value; public: special(std::string name, T value) : generic(std::move(name)), _value(std::move(value)) {} ~special() override = default; std::string value() override { return std::to_string(_value); } }; template <typename T> void add_item(std::map<std::string, std::unique_ptr<generic>>& m, const std::string& n, const T& v) { m[n] = std::make_unique<special<T>>(typeid(v).name(), v); // 必须用引用遍历,值遍历会尝试拷贝unique_ptr触发编译错误 for (const auto& i : m) { std::cout << "add_item: " << i.first << " -- " << i.second->name() << " -- " << i.second->value() << std::endl; } } int main() { std::map<std::string, std::unique_ptr<generic>> instances; add_item<int>(instances, "int", 1); add_item<bool>(instances, "bool", true); add_item<float>(instances, "float", 3.1415f); // 引用遍历,直接通过智能指针的->操作符调用虚函数即可,无需显式调用get()取裸指针 for (const auto& i : instances) { std::cout << i.first << " -- " << i.second->name() << " -- " << i.second->value() << std::endl; } return 0; }
补充说明
- 如果需要在多个代码位置共享同一个实例,可以将
std::unique_ptr替换为std::shared_ptr,创建对象的方法对应替换为std::make_shared即可。 - 不要使用值类型存储多态对象,所有需要运行时多态的场景都要通过指针或引用访问对象。
内容的提问来源于stack exchange,提问作者ZioByte
相关产品推荐
相关产品推荐

