多态性和shared_ptr成员

Kae*_*Kae 5 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;
};
Run Code Online (Sandbox Code Playgroud)

现在,我们可以拥有主力

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

除非我不包括从我的实际代码的小例子,有些错误,我觉得SomeC是越来越切下来的B,或者至少someBMethodB正在calledin的最后一行.

问:应该用什么来初始化正确的方式Member以这样的方式,该方法someBMethodC被调用?

Bey*_*ios 7

你正在通过调用执行切片std::make_shared<B>(SomeB)这将构造一个指向类型的对象的shared_ptr ,B并通过使用B上的copy-constructor来构造该对象:B::B(const B& b)切掉关于C-ness的所有信息SomeB.

将A更改为:

class A{
public:
  A(const std::shared_ptr<B>& pB) : pMember(pB) {}
  std::shared_ptr<B> pMember;
};
Run Code Online (Sandbox Code Playgroud)

主要:

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

  • @PiotrS.这是通过使用超类的复制构造函数来完成的 - 你能解释一下这里有什么区别吗? (2认同)

Mik*_*our 3

我认为SomeC被分割成B

这正是正在发生的事情。make_shared创建指定类型的新对象,将其参数转发给合适的构造函数。因此,这会创建一个新的B,并使用其复制构造函数来复制 的B子对象进行初始化SomeC

以调用Member方法的方式进行初始化的正确方法应该是什么?someBMethodC

这很棘手:C不是共享的,而是Member共享的,而且你不能两者兼得。如果您要求用户传递一个共享指针,暴露它要与此类共享的事实,这可能是最好的:

A(std::shared_ptr<B> SomeB) : Member(SomeB){}
Run Code Online (Sandbox Code Playgroud)

如果您确实想允许它使用非共享对象,您可以使用虚拟删除器创建一个共享指针,这样它就不会尝试共享所有权:

A(B& SomeB) : Member(std::shared_ptr<B>(&SomeB, [](B*){})){}
Run Code Online (Sandbox Code Playgroud)

但请注意,您现在有责任确保C在 之后 之前不会被销毁A,并且它的任何副本都不再需要它。您已经失去了“拥有”共享指针的安全性。

无论您做什么,都不要简单地从&SomeB. 默认删除程序将尝试删除它,这是一个错误,因为它不是动态创建的。