[英]Polymorphism and shared_ptr member
测试多态性和虚函数&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
我认为SomeC
会被切成B
,或者至少有someBMethod
来自B
的BMethod在最后一行被调用。
问题:以这样的方式初始化Member
的正确方法是什么?来自C
someBMethod
方法被调用?
你正在通过调用std::make_shared<B>(SomeB)
执行切片这将构造一个指向类型B
的新对象的shared_ptr,并使用B: B::B(const B& b)
上的copy-constructor构造该对象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.
}
我认为
SomeC
会被切成B
这正是发生的事情。 make_shared
创建一个指定类型的新对象,将其参数转发给合适的构造函数。 所以这使得一个新的B
,使用其拷贝构造函数初始化来复制SomeC
的B
子对象。
以这样的方式初始化
Member
的正确方法是什么?来自C
的方法someBMethod
被调用?
这很棘手: C
不是共享的,但Member
是,而且你不可能双管齐下。 如果您要求用户传入共享指针,则可能是最好的,因为它暴露了要与此类共享的事实:
A(std::shared_ptr<B> SomeB) : Member(SomeB){}
如果您确实希望允许它使用非共享对象,则可以使用虚拟删除器创建共享指针,因此它不会尝试共享所有权:
A(B& SomeB) : Member(std::shared_ptr<B>(&SomeB, [](B*){})){}
但请注意,您现在有责任确保在A
之后不会销毁C
,并且不再需要它的任何副本。 你已经失去了“拥有”共享指针的安全性。
无论你做什么,都不要简单地从&SomeB
创建一个共享指针。 默认删除器将尝试删除它,这是一个错误,因为它不是动态创建的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.