[英]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 aB
我认为
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
,使用其拷贝构造函数初始化来复制SomeC
的B
子对象。
What should be the right way to initialize
Member
in such a way that the methodsomeBMethod
fromC
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.