多态性和shared_ptr成员

时间:2014-10-08 16:01:49

标签: c++ polymorphism shared-ptr

测试多态性&虚拟功能& shared_ptr,我试图理解以下最小例子描述的情况。

class B{
public:
  // Definition of class B
  virtual void someBMethod(){
   // Make a burger
  };
};

class C : public B {
public:
  // Definition of class C
  void someBMethod(){
   // Make a pizza
  };
};

class A{
public:
  A(B& SomeB) : Member(std::make_shared<B>(SomeB)){};
  std::shared_ptr<B> Member;
};

现在,主要是我们可以

int main(){
  C SomeC;
  A SomeA(SomeC);
  A.Member->someBMethod(); // someBMethod from B is being executed.
};

除非我没有从实际代码到最小示例中包含一些错误,否则我认为SomeC会从B切割为someBMethod,或者至少从B Member被称为最后一行。

问题:以someBMethod中的C方法调用方式初始化{{1}}的正确方法是什么?

2 个答案:

答案 0 :(得分:6)

您通过调用std::make_shared<B>(SomeB)来执行slicing这将构建一个指向类型为B new 对象的shared_ptr,并通过以下方式构造该对象使用B上的复制构造函数:B::B(const B& b)切除有关SomeB的C-ness的所有信息。

将A更改为:

class A{
public:
  A(const std::shared_ptr<B>& pB) : pMember(pB) {}
  std::shared_ptr<B> pMember;
};

主要:

int main(){
  A SomeA(std::make_shared<C>());
  A.pMember->someBMethod(); // someBMethod from C is being executed.
}

答案 1 :(得分:3)

  

我认为SomeC正逐渐变为B

这正是发生了什么。 make_shared创建一个指定类型的新对象,将其参数转发给合适的构造函数。因此,这会生成一个新的B,使用其复制构造函数进行初始化,以复制B的{​​{1}}子对象。

  

SomeC中的方法Member被调用的方式初始化someBMethod的正确方法是什么?

这很棘手:C未被分享,但是C是,并且你无法双管齐下。如果您要求用户传入共享指针,那么它可能是最好的,这表明它将与此类共享:

Member

如果你真的想让它使用非共享对象,你可以创建一个带有虚拟删除器的共享指针,因此它不会尝试共享所有权:

A(std::shared_ptr<B> SomeB) : Member(SomeB){}

但请注意,您现在有责任确保在A(B& SomeB) : Member(std::shared_ptr<B>(&SomeB, [](B*){})){} 之后C不被销毁,并且其任何副本不再需要它。你已经失去了拥有&#34;拥有&#34;共享指针。

无论你做什么,都不要简单地从A创建共享指针。默认删除器将尝试删除它,这是一个错误,因为它没有动态创建。