1. 程式人生 > >C++之複製物件時勿忘每一個成分(12)---《Effective C++》

C++之複製物件時勿忘每一個成分(12)---《Effective C++》

條款12:賦值物件時勿忘其每一個成分

C++中設計良好的物件系統會將物件的內部封裝起來,只留下兩個函式負責物件那個拷貝(賦值),即copy建構函式和copy operator=。
如果我們自己宣告自己的copying函式,則C++的編譯器則不會對我們自己提供的copying函式進行檢驗,即使copying函數出錯了編譯器並不會報錯。
具體參看如下程式碼:

class A{
public:
    A(const A&);
    A& opreator=(const A&);
    ...
private:
    std::string A_a;
}
A::
A(const A&a){ this->A_a=a->A_a; } A& A::operator::=(const A& a){ if(this==&a) return *this; this->A_a=a->A_a; return *this; }

可是如果此時我們將A中加入新的變數呢?

class B{};
class A{
public:
    ...
private:
    std::string A_a;
    B b;
}

這時候,copying建構函式只是簡單的複製了A_a,對於b成員變數並沒有進行復制,大多數編譯器無法檢測出這些問題,因此,我們必須:
1)如果我們為類新增一個成員變數,必須同時修改copying函式,同時包括建構函式和一些非標準的operator=函式;

如果發生繼承呢?

class A{
public:
    ...
    A(const A&a);
    A& operator=(const A&a);
private:
    std::string name;
}
class B:public A{
public:
    ...
    B(const B&b);
    B& operator=(const B&b);
private:
    int x;
}
B::B(const B&b):A(b){
    ...
}
B& B::operator=(const B&b){
    A::operator=(b);
    this->x=b.x;
    return
*this; }

2)可以發現對於繼承體系中,當你編寫子類的copying函式,請確保

  • 列表內容
  • 複製所有local成員變數 ,同時呼叫所有的base classes中適當的copying函式
    PS:注意此時不能用copy與建構函式呼叫copy assignment運算,同時copy assignment也不能呼叫copy建構函式,不合理,因為這樣相當於試圖呼叫一個已經存在的物件;
    總結:
    1)copying函式應該確保賦值“物件內的所有成員變數”和“所有基類成分”;
    2)不要嘗試以某個copying函式實現另一個copying函式,應該共同放在第三個函式中,並有兩個copying函式呼叫。