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,或者至少someBMethod从B正在calledin的最后一行.
问:应该用什么来初始化正确的方式Member以这样的方式,该方法someBMethod从C被调用?
你正在通过调用执行切片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)
我认为
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. 默认删除程序将尝试删除它,这是一个错误,因为它不是动态创建的。