天天看點

Effective C++ 2e Item27

條款27: 如果不想使用隐式生成的函數就要顯式地禁止它

假設想寫一個類模闆Array,它所生成的類除了可以進行上下限檢查外,其它行為和C++标準數組一樣。設計中面臨的一個問題是怎麼禁止掉Array對象之間的指派操作,因為對标準C++數組來說指派是不合法的:

double values1[10];

double values2[10];

values1 = values2;                 // 錯誤!

對很多函數來說,這不是個問題。如果你不想使用某個函數,隻用簡單地不把它放進類中。然而,指派運算符屬于那種與衆不同的成員函數,當你沒有去寫這個函數時,C++會幫你寫一個(見條款45)。那麼,該怎麼辦呢?

方法是聲明這個函數(operator=),并使之為private。顯式地聲明一個成員函數,就防止了編譯器去自動生成它的版本;使函數為private,就防止了别人去調用它。

但是,這個方法還不是很安全,成員函數和友元函數還是可以調用私有函數,除非——如果你夠聰明的話——不去定義(實作)這個函數。這樣,當無意間調用了這個函數時,程式在連結時就會報錯。

對于Array來說,模闆的定義可以象這樣開始:

template<class T>

class Array {

private:

  // 不要定義這個函數!

  Array& operator=(const Array& rhs);

  ...

};

現在,當使用者試圖對Array對象執行指派操作時,編譯器會不答應;當你自己無意間在成員或友元函數中調用它時,連結器會嗷嗷大叫。

不要因為這個例子就認為本條款隻适用于指派運算符。不是這樣的。它适用于條款45所介紹的每一個編譯器自動生成的函數。實際應用中,你會發現指派和拷貝構造函數具有行為上的相似性(見條款11和16),這意味着幾乎任何時候當你想禁止它們其中的一個時,就也要禁止另外一個。