簡體   English   中英

多態性和shared_ptr成員

[英]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 ,使用其拷貝構造函數初始化來復制SomeCB子對象。

以這樣的方式初始化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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM