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函數共同調用。