條款10 若不想使用編譯器自動生成的函式,就該明確拒絕
阿新 • • 發佈:2020-07-05
如果一個物件,只是希望他可以被創造出來,不希望被拷貝,那麼最先想到的應該是將拷貝和複製運算子私有化:
class A { public: A(){} ~A(){} private: A(const A&){} A& operator=(const A&) {} };
但是書中大師認為,有兩類函式仍然可以訪問:成員函式和友元函式,如下:
#include<iostream> using namespace std; class A { public: A(){} ~A(){} friend voidMyCopyA_One(); void MyCopyA_Two() { A a; A b(a); b = a; } private: A(const A&){} A& operator=(const A&) {} }; void MyCopyA_One() { A a; A b(a); b = a; } int main() { MyCopyA_One(); A a; a.MyCopyA_Two(); while (1); return 0; }
解決方法是對於私有的拷貝建構函式和賦值運算不定義,那麼連結的時候就會因為找不到拷貝或者賦值運算的定義而連結失敗,如下:
但是這個錯誤是在連結的時候才會有的,能不能把錯誤提前到編譯時期,於是大師為我們提供瞭如下方案:
#include<iostream> using namespace std; class Uncopyable { public: Uncopyable(){} ~Uncopyable(){} private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); }; class A :private Uncopyable { public: }; int main() { A a; //A b(a); 編譯不過 //b = a; 編譯不過 while (1); return 0; }
解釋:因為子類在呼叫建構函式時先會呼叫父類的建構函式,這裡由於父類沒有定義,所以會編譯不過。