簡體   English   中英

C++ 我應該覆蓋派生類中的復制構造函數嗎

[英]C++ Should I overwrite copy constructor in derived class

我有帶有自定義復制構造函數的基類,可以處理分配的內存。 我也有從那個基礎派生的課程。 該派生類沒有對內存做更多的事情。

復制構造函數在派生類中應該如何看待? 覆蓋交換,移動和分配怎么樣?

除了可能為swap之外,您不應該做任何事情。 在這方面,基類就像一個數據成員,編譯器生成的復制構造函數和賦值(如果適用,還可以移動)包括它。

swap是不同的,因為沒有編譯器生成的swap ,只有命名空間std中的默認實現,然后是程序員為用戶定義的類型定義的任何專業化或 ADL 重載。

因此,如果已經有一個看起來像這樣的函數:

namespace foo {
    void swap(Base &lhs, Base &rhs) {
        lhs.swap(rhs); // or maybe the gory details are in this function
    }
}

你什么也不做,有些用戶這樣稱呼它:

foo::swap(derived1, derived2);

然后基礎部分將被交換,而派生部分不會,這很糟糕。

用戶不應該那樣調用swap ,但你知道用戶是什么樣的。 如果BaseDerived在同一個命名空間中,用戶可能會覺得特別誘人,並且他們只是假設它會全部工作。 因此,如果您認為您的用戶(或您自己的代碼庫)在調用swap的方式上沒有原則,您可能希望確保Derived有一個重載以阻止它們。

用戶應該像這樣調用swap

using std::swap;
swap(base1, base2);
swap(derived1, derived2);

這將在與Base一起使用時調用foo::swap ,在與Derived一起調用時調用std::swap std::swap<Derived>可能效率低下(如果Base實現了交換以提高效率,那么Derived也應該如此)。 因此,出於這個原因,您可能也想為Derived實現swap ,但慢並不像錯誤那么糟糕。

也就是說,你問的是動作。 如果Derived可以有效地移動,那么std::swap<Derived>還不錯。 也許它可以改進,也許不能,但它應該是微不足道的,因為三步是很難擊敗的。

您和用戶還應該意識到, swap不能很好地與多態性配合使用(因為通常兩個對象必須具有相同的完整類型才能使它們交換有意義),並且為基類實現它可能會導致麻煩。

Derived d1, d2;
Base &b1 = &d1, &b2 = d2;
swap(b1, d2); // swaps just the base part
swap(b1, b2); // swaps just the base part

所以首先,用戶需要知道不要那樣調用swap。 其次,您可能要考慮帶有swapBase是否真的被精心設計為基類。

有所謂的五規則(以前的三規則),它表示如果您有用戶定義的其中任何一個:

  • 復制構造函數
  • 移動構造函數
  • 析構函數
  • 復制賦值運算符
  • 移動賦值運算符

比您可能還想用戶定義其他四個。


另一方面, 有零規則:您可以使用自動處理這些事情的資源對象 (RAII),而不是定義這五個特殊成員函數。

不管這樣的對象是某個C類的數據成員還是基類(子對象):編譯器提供的隱式聲明和定義的C的特殊成員函數將調用該資源對象的特殊成員函數,這很可能就足夠了。

提示:具體例子可以給出更准確的答案

您不能“覆蓋”構造函數。 它不是 C++ 詞匯表中的術語。 您可以覆蓋一個函數,但前提是它是虛擬的。

通常你不應該在任何正確編寫的基類的子類的構造函數中做任何特殊的事情。 讓每一代人照顧好自己。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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