條款12:複製對象時勿忘其每個部分

設計良好的面向對象系統會將對象的內部封裝起來,只留兩個函數負責對象拷貝,即copy構造函數與copy assignment操做符。編譯器會在必要的時候爲類建立coping函數,並說明這些「編譯器生成版」的行爲:將被拷貝對象的全部成員變量都作一份拷貝。安全

任什麼時候候,只要本身實現派生類的copying函數,則必須很當心的複製其基類成分。這些成分每每是private私有的,故沒法直接訪問它們,所以應該讓派送類的coping函數調用相應的基類函數:函數

 void logCall(const string& funcName);
class Customer { public:
     ... Customer(const Customer& rhs); Customer& operator=(const Customer& rhs);
     ... private: string name; Date lastTranscation; };

  

 class PriorityCustomer : public Customer
 {
 public:
     ...
	 PriorityCustomer(const PriorityCustomer& rhs);
	 PriorityCustomer& operator=(const PriorityCustomer& rhs);
      ...
 private:
	 int priority;
 };

 PriorityCustomer ::PriorityCustomer (const PriorityCustomer& rhs) 
	 : Customer(rhs),	//調用基類的copy構造函數
	 priority(rhs.priority)
 {
	 logCall("PriorityCustomer copy constructor");
 }

 PriorityCustomer& PriorityCustomer ::operator = (const PriorityCustomer& rhs) 
 {
	 logCall("PriorityCustomer copy assignment constructor");
	 Customer::operator=(rhs);	//對基類Customer成分進行復制動做
	 priority = rhs.priority;
	 return *this;
 }

當編寫一個copying函數,確保一、複製全部local成員變量,二、調用全部基類的適當的copying函數。this

注意兩個錯誤用法:一、令copy assignment操做符調用copy構造函數是錯誤的,由於在這就像試圖構造一個已存在的對象。spa

         二、令copy構造函數調用copy assignment操做符一樣是錯誤的。構造函數用來出過後對象,而assignment操做符只實行與已初始化的對象身上。對一個還沒有構造好的對象賦值,就像在一個還沒有初始化的對象身上作「z只對已初始化對象纔有意義」的事意義。設計

消除copy構造函數與copy assignment操做符重複代碼的作法是:創建一個新的成員函數給二者調用。這樣的函數每每是private並且被命名爲init。這個策略能夠安全消除copy構造函數與copy assignment操做符之間的代碼重複。對象

請牢記:blog

  一、copying 函數應該確保複製「對象內的全部成員變量」及「全部基類成分」。編譯器

  二、不要嘗試以某個copying函數實現另外一個copying函數。應該將共同機能放進第三個函數中,並由兩個copying函數共同調用。string

相關文章
相關標籤/搜索