简体   繁体   English

多态性和shared_ptr成员

[英]Polymorphism and shared_ptr member

Testing polymorphism & virtual functions & shared_ptr, I am trying to understand the situation described by the following minimal example. 测试多态性和虚函数&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;
};

Now, in the main we can have 现在,我们可以拥有主力

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

Unless I didn't include some mistake from my actual code to the minimal example, I think SomeC is getting sliced down to a B , or at least someBMethod from B is being calledin the last line. 除非我没有将实际代码中的一些错误包含在最小的例子中, SomeC我认为SomeC会被切成B ,或者至少有someBMethod来自B的BMethod在最后一行被调​​用。

Question: What should be the right way to initialize Member in such a way that the method someBMethod from C gets called? 问题:以这样的方式初始化Member的正确方法是什么?来自C someBMethod方法被调用?

you're performing slicing by calling std::make_shared<B>(SomeB) This will construct a shared_ptr pointing to a new object of type B and construct that object by using the copy-constructor on B: B::B(const B& b) slicing off all information about the C-ness of SomeB . 你正在通过调用std::make_shared<B>(SomeB)执行切片这将构造一个指向类型B对象的shared_ptr,并使用B: B::B(const B& b)上的copy-constructor构造该对象B::B(const B& b)切掉关于SomeB的C-ness的所有信息。

change A to: 将A更改为:

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

And main: 主要:

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

I think SomeC is getting sliced down to a B 我认为SomeC会被切成B

That's exactly what's happening. 这正是发生的事情。 make_shared makes a new object of the specified type, forwarding its arguments to a suitable constructor. make_shared创建一个指定类型的新对象,将其参数转发给合适的构造函数。 So this makes a new B , initialised using its copy-constructor to copy the B sub-object of SomeC . 所以这使得一个新的B ,使用其拷贝构造函数初始化来复制SomeCB子对象。

What should be the right way to initialize Member in such a way that the method someBMethod from C gets called? 以这样的方式初始化Member的正确方法是什么?来自C的方法someBMethod被调用?

That's tricky: C is not shared, but Member is, and you can't have it both ways. 这很棘手: C不是共享的,但Member是,而且你不可能双管齐下。 It's probably best if you require the user to pass in a shared pointer, exposing the fact that it is to be shared with this class: 如果您要求用户传入共享指针,则可能是最好的,因为它暴露了要与此类共享的事实:

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

If you really want to allow it to use a non-shared object, you could create a shared pointer with a dummy deleter, so it doesn't try to share ownership: 如果您确实希望允许它使用非共享对象,则可以使用虚拟删除器创建共享指针,因此它不会尝试共享所有权:

A(B& SomeB) : Member(std::shared_ptr<B>(&SomeB, [](B*){})){}

but beware that you are now responsible for ensuring that C isn't destroyed until after A , and any copy of it, no longer requires it. 但请注意,您现在有责任确保在A之后不会销毁C ,并且不再需要它的任何副本。 You've lost the safety of an "owning" shared pointer. 你已经失去了“拥有”共享指针的安全性。

Whatever you do, don't simply create a shared pointer from &SomeB . 无论你做什么,都不要简单地从&SomeB创建一个共享指针。 The default deleter will try to delete it, which is an error because it wasn't dynamically created. 默认删除器将尝试删除它,这是一个错误,因为它不是动态创建的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM