C++之複製物件時勿忘每一個成分(12)---《Effective C++》
阿新 • • 發佈:2019-01-04
條款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函式呼叫。