effective c++乾貨之條款06:若不想使用編譯器自動生成的函式,就該明確拒絕
阿新 • • 發佈:2018-12-15
假如你建立了一個類用來表示世界上的每一個人:
class aPerson
{
//...
};
每一個人都是獨一無二的,所以為一個人做一個副本顯得有悖倫理道德,那麼我們就應該禁止拷貝構造和copy assignment操作(統稱為copying 函式)。
不幸的是,如果我們自己沒有實現copying函式,那麼編譯器會自作多情的為我們實現一份。所以為了覆蓋它們,我們需要自己實現copying函式,然而如果自己實現了copying函式,那麼和編譯器自動生成的又有什麼區別呢,那不是多此一舉嗎?
為了解決這個問題,我們首先
(1). 可以將自己生成的copying函式宣告為private,這樣當用戶企圖做一份副本時編譯器就會報錯。
class MyClass
{
private:
int SomeValue;
private:
MyClass(const MyClass &Temp):SomeValue(Temp.SomeValue){}
MyClass &operator =(const MyClass &Temp)
{
SomeValue = Temp.SomeValue ;
return *this;
}
};
但當你使用member函式或者是friend函式時,還是有可能呼叫private函式。
(2). 我們可以僅宣告copying函式,而不去定義它們,這樣當用戶企圖做一份副本時連結器也會報錯。
class MyClass
{
private:
int SomeValue;
private:
MyClass(const MyClass &Temp);
MyClass &operator =(const MyClass &Temp);
};
如果專案很大,編譯過程很長,等到連結器報錯豈不是白白編譯了半天?能不能把錯誤提前到編譯期呢?
(3). 我們只需要定義一個父類,將父類的copying函式宣告為private,然後用類去繼承它即可。
class NoCopy { //... private: NoCopy(const NoCopy &Temp); NoCopy &operator =(const NoCopy &Temp); //... }; class MyClass private: NoCopy { //不需要再次實現copying函式 };
這麼做的理由是:如果你試圖給一個MyClass物件做一個副本,那麼編譯期自動生成的copying函式就會嘗試呼叫父類中的copying函式(因為子類的copying函式只複製子類成員,父類成員也需要複製),而父類中copying函式為private。