2016-08-15 40 views
2

我我的C期間,在2個愚蠢的問題絆倒++ practixe:如何提高::不可複製工作

  1. 在C++ AFAIK拷貝構造函數和賦值操作符是不可繼承......所以如何提高::在這種情況下禁止這種東西的不可複製的幫助?

     
    class X: private boost::noncopyable 
    { 
    }; 
    
    是否有必要僅使用私有繼承來實現目標?

  2. 是否只有一種方法來聲明賦值運算符

     
    MyClass& operator= (const MyClass &); 
    
    聲明
     
    void operator= (const MyClass &);
     
    const MyClass& operator= (const MyClass &);
    是否是一樣的東西?

+2

它們不是繼承的。但編譯器生成的調用所有的基類複製c'tors ... – StoryTeller

+0

它不必私下繼承,但這樣做可以防止愚蠢的代碼,如'boost :: noncopyable const&x = X {};' – Praetorian

回答

2

在C++ 11及更高版本中的不可複製將通過聲明它爲=delete,最好是公共的。然而,在C++ 11,這是不可能的,2個技術組合使用:

  • 聲明私有方法
  • 沒有實現方法

通過製作方法私人,這不能被非朋友類調用。因此,任何試圖調用此代碼的代碼都會導致編譯錯誤。

實際上,班級仍然可以自我複製。因此這個方法沒有得到實現,你會得到一個鏈接器錯誤。

boost::noncopyable繼承將阻止第二個用例,但是,它也可以防止編譯器可以生成有效的默認拷貝構造函數...因爲它們將違反先前的約束。

請注意,如果您確實需要,可以通過調用這些「不可複製」類的普通構造函數來爲繼承類編寫複製構造函數。

對於第二個問題:是的,你可以給它任何你想要的返回類型,儘管你不能再寫a = b = c;

+1

@Quentin Tnx,那就是我的意思! – JVApen

+0

謝謝,這是對我的完整解釋! – Dmitry

0

1)當構造對象時,還必須構造所有成員對象和基礎對象。由於noncopyable::noncopyable(const noncopyable &)是私人的,因此noncopyable不能被複制。因此,包含它作爲成員或基地的任何對象也不能被複制構建。

2)您可以將您描述的三種方法中的任何一種聲明爲您的賦值操作符。不,他們不是「同一件事」。一個返回一個可變引用,一個返回一個const引用,另一個返回void。如果您嘗試對賦值運算符的結果進行操作,則區別將會很明顯。考慮這個程序片段:

a = b; 
(a = b).foo() 

第一行將與您的任何賦值操作符一樣操作。第二行將根據您使用的賦值運算符而有所不同。

+1

[ 'boost :: noncopyable'](http://www.boost.org/doc/libs/1_55_0/boost/noncopyable.hpp)是可以構造的。 – NathanOliver

+1

我不認爲'boost :: noncopyable :: noncopyable()'是私有的。 – aschepler

+0

它不能是私有的,因爲那意味着你不能構建你的初始實例。 – JVApen

1

複製構造函數和複製賦值運算符沒有被繼承是正確的。幸運的是,我們並不需要它們繼承以使其發揮作用。如果你從一個不能被複制的類繼承,那麼這個派生類不能被複制,也不能在它的拷貝構造函數中調用基類拷貝構造函數。

基本你從一個類繼承看起來像

struct NonCopyable { 
    NonCopyable & operator=(const NonCopyable&) = delete; 
    NonCopyable(const NonCopyable&) = delete; 
    NonCopyable() = default; 
}; 

這足以停止工作在派生類中的編譯器生成的拷貝和賦值。你可以提供你自己的並且覆蓋這個,但是那就是擊敗了這一點。