1. 程式人生 > >effective c++乾貨之條款06:若不想使用編譯器自動生成的函式,就該明確拒絕

effective c++乾貨之條款06:若不想使用編譯器自動生成的函式,就該明確拒絕

假如你建立了一個類用來表示世界上的每一個人:

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。