C++:在容器的 STL 容器中存储派生类的实例指针

问题描述

我阅读了Passing shared_ptr<Derived> as shared_ptr<Base>,但这并没有回答我的问题。

假设我们有

class Base
{
};

class Derived : public Base
{
};

我想创建以下容器:std::map<int,std::shared_ptr<std::unordered_map<std::string,std::shared_ptr<Base>>>> _channels;

我需要将实例添加为类型为 std::shared_ptr<std::unordered_map<std::string,std::shared_ptr<Base>>>std::shared_ptr<std::unordered_map<std::string,std::shared_ptr<Derived>>> 的值。

很遗憾,我无法添加类型为 Derived 的实例,但类型为 Base 的情况很好。

完整代码

#include <iostream>
#include <string>
#include <map>
#include <unordered_map>
#include <memory>
#include <utility>

class Base
{
};

class Derived : public Base
{
};

int main()
{
// works fine
/*
    std::map<int,std::shared_ptr<Base>> _channels2;
    _channels2.emplace(std::pair<int,std::shared_ptr<Derived>>(3,std::make_shared<Derived>()));
    std::cout << "_channels2.size() = " << _channels2.size() << std::endl;
*/

// fails to compile
    std::map<int,std::shared_ptr<Base>>>> _channels;
    _channels.emplace(std::pair<int,std::shared_ptr<Derived>>>>(2,std::make_shared<std::unordered_map<std::string,std::shared_ptr<Derived>>>()));
    std::cout << "_channels.size() = " << _channels.size() << std::endl;

    return 0;
}

我使用的是 C++14。

  1. 我是否理解得很好,所以它无法编译的原因是因为 std::shared_ptr<std::unordered_map<std::string,std::shared_ptr<Derived>>> 不是 std::shared_ptr<std::unordered_map<std::string,std::shared_ptr<Base>>> 的子类型?所以多态在这种情况下不可用。

  2. 有没有您可以建议的解决方法

谢谢。

解决方法

考虑到这可行,您可以尝试一些方法:

std::map<std::string,std::shared_ptr<Derived>> derived_map;
std::map<std::string,std::shared_ptr<Base>> base_map(derived_map.begin(),derived_map.end());

因此你可以写:

std::shared_ptr<std::unordered_map<std::string,std::shared_ptr<Derived>>> derived_map;
auto base_map = std::make_shared<std::unordered_map<std::string,std::shared_ptr<Base>>>(derived_map->begin(),derived_map->end());

等等......缺点是只有基础和派生是“共享的”,地图是重复的。