【问题标题】:Vector of shared_ptr of a abstract bass class pointing to derived classes指向派生类的抽象bass类的shared_ptr向量
【发布时间】:2020-03-23 21:11:33
【问题描述】:

我在一个类中,我应该使用抽象基类和派生类的两级层次结构创建共享指针向量。

class Base
{
   virtual string returnName() = 0;
};

class DerivedOne : public Base
{
private:
   string name;

public:
   DerivedOne()
   {name = "Derived";}

   virtual string returnName()
   {return name;}
};

class DerivedTwo : public DerivedOne
{
private:
   string secondName;

public:
   DerivedTwo()
   {secondName  = "DerivedTwo";}

   virtual string returnName()
   {return secondName;}
};

int main()
{
   vector<shared_ptr<Base>> entities;
   entities.push_back(new DerivedOne());

   return 0;
}

我的问题是使用push_back() 将派生类添加到向量的末尾,并在编译时显示no matching function for call to ‘std::vector&lt;std::shared_ptr&lt;Base&gt; &gt;::push_back(DerivedOne*)

如何将初始化的派生类添加到向量中?

【问题讨论】:

  • 您可以通过将原始指针转换为std::shared_ptr 来使其工作,因为std::shared_ptr ctor 是显式的。但是你最好还是使用std::make_shared()

标签: c++ vector shared-ptr


【解决方案1】:

您应该完全避免使用原始的new。相反,您应该使用std::make_shared 分配将由std::shared_ptrs 管理的对象:

entities.push_back(std::make_shared<DerivedOne>());

std::make_shared 向新分配的对象返回 std::shared_ptr,而不是原始指针。这不仅使std::vector::push_back 在这种情况下工作,而且在面对异常时也不太可能泄漏内存。

【讨论】:

  • 那行得通。你会只使用带有原始指针的原始new 吗?
  • Raw new 返回一个原始指针,您应该尽可能避免使用原始指针。在现代 C++ 中直接使用 new 的理由很少。
【解决方案2】:

您需要将此行替换为

entities.emplace_back(new DerivedOne());

因为您不想push_back Base* 而是std::shared_ptr&lt;Base&gt;。使用emplace 将允许在std::shared_ptr&lt;Base&gt; 的构造函数中使用Base*,然后将其添加到您的向量中。

【讨论】:

  • 我认为这行不通,因为 shared_ptr 不能从原始指针隐式构造。
  • @j6t 它编译了ideone.com/yKrRUk,但最好还是调用std::make_shared()
  • @j6t std::shared_ptr&lt;T&gt;(T*) 肯定有一个构造函数,参见the docs
  • 我认为@j6t 意味着它不会因为这样的ctor是明确的
  • @Slava 我明白了。它之所以起作用,是因为在幕后,emplace() 必须调用 new (addr) std::shared_ptr&lt;Base&gt;(arg),而且这是足够明确的,因此这个 explicit 构造函数是可行的。
猜你喜欢
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-05
  • 2020-03-27
相关资源
最近更新 更多