2013-10-10 66 views
0

我有一個繼承另一個類(類B)的類(A類)。在派生類中複製構造和賦值運算符

class A: public B 

B類禁用的複製構造和賦值操作符(由於不允許副本)。

private: 
B(const B&); 
B& operator=(const B&); 

我的問題是,是否也應該禁止拷貝構造和賦值操作符在派生類中一樣好,甚至是好的,如果我沒有界定兩者。

+0

取決於* how * did B是否禁用copy-ctor。 – jrok

+0

@jrok爲什麼?無論B禁用複製和分配如何,它們在派生類中都被默認禁用。 –

+0

@JamesKanze我在計算把它放在'protected'部分中作爲「禁用」它。 – jrok

回答

1

問題是,你應該重新啓用它。如果任何基地或成員不可複製,則默認情況下,您的課程將不可複製。一般來說,你不想刪除它,因爲要給它合理的語義很難或不可能。但有一些明顯的例外:如果基類是抽象的,例如,您可能希望在派生類中啓用複製構造函數(但不分配)以支持克隆。

+0

如果我在派生類中有一個指針變量,我得到了一個警告,我應該定義複製構造和賦值運算符。我應該考慮另一種解決方案(即沒有任何指針)嗎?或者是好的,如果我定義它們並在派生類中禁用它們? –

+0

@AvbAvb如果在基類中禁用了複製和分配,並且沒有重新啓用,則警告完全錯誤。我會關閉它(也許抱怨編譯器廠商)。 –

3

子類應該具有與其父類相同或更嚴格的[先決條件,後置條件和不變式]。這是Liskov Substitution Principle。所以,你不應該在派生類中重新啓用複製構造等等,因爲你將會放寬基類的合約。

如果您發現您需要這樣做(或者真的想這樣做),那麼這可能表明您需要重新考慮您的設計。

+0

我不想重新啓用它們。我只是問我是否也應該在派生類中禁用它們,或者如果我在派生類中沒有做任何事情,它是否可以。 –

+0

對不起,我認爲你已經知道默認行爲是派生類將從複製構造和賦值方面「繼承」基類的契約。如果你明確地表達了你的意圖,那就更清楚了。 「我希望Derived與Base有相同的限制,我在Base中做什麼?「,我會回答」沒有「,一切都很好。 –

0

如果不允許拷貝構造函數和基類的賦值運算符將導致派生類的拷貝構造函數和賦值運算符將無法使用,以及:

class B { 
public: 
    B() { } 
private: 
    B(const B&); 
    B& operator=(const B&); 
}; 

class A : public B { }; 

在這種情況下,你不需要明確地禁止這些派生類,因爲默認實現將不得不首先使用父實現。因此,如果您不嘗試訪問您的代碼中的這些內容:

int main() { 
    A a; 
} 

它將完全有效。但是,如果您嘗試複製:

int main() { 
    A a; 
    A a2 = A(a); 
} 

編譯器會抱怨類A試圖訪問的B私有成員(但語義上的第二個方案是不應該的)。

相關問題