Item 12-復制對象時忽忘其每一個成分(Copy all parts of an object)
設計良好之面向對象系統(OO-system)會將對象的內部封裝起來,只留兩個函數負責將對象拷貝(復制),那便是帶著適切名稱的copy構造函數和copy assignment操作符,稱它們為copying函數。
如果是"編譯器生成版本"的行為:將被拷對象的所有成員變量都做一份拷貝。
如果是自己聲明就要注意了。
如果是為"derived class撰寫copying函數"的重大責任,必須很小心的復制其base class成分。那些成分往往是private,所以你無法直接訪問它們,你應該讓derived class的copying函數調用相應的base class函數。
Ex:
class Customer //base class
{
public:
...
Customer(const Customer& rhs);
Customer& operator = (const Customer& rhs);
...
private:
string name;
}
Customer::Customer(const Customer& rhs):name(rhs.name);
Customer::Customer& operator=(const Customer& rhs)
{
name=rhs.name;
return *this;
}
class PriorityCustomer:public Customer //derived class
{
public:
...
PriorityCustomer(const PriorityCustomer& rhs);
PriorityCustomer& operator=(const PriorityCustomer& rhs);
...
private:
int priority;
}
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):Customer(rhs),priority(rhs.priority);
PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
Customer::operator=(rhs) //對base class成分進行賦值動作
priority=rhs.priority;
return *this;
}
"復制每一個成分"即復制所有local成員變量,調用所有base classes內的適當的copying函數
令copy assignment操作符調用copy構造函數是不合理的,因為這就像試圖構造一個已經存在的對象。
令copy構造函數調用copy assignment操作符也沒有意義。
如果copy構造函數和copy assignment操作符有相近的代碼,消除重復代碼的做法是,建立一個新的成員函數給兩者調用。這樣的做法往往private,而且常被命名為init。這個策略可以安全消除copy構造函數和copy assignment操作符之間的代碼重復。
請記住:
copying函數應該確保復制"對象內的所有成員變量"及所有"base class"成分
不要嘗試以某個copying函數實現另一個copying函數。應該將共同機能放進第三個函數中,並由兩個copying函數共同調用。