[英]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.