首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Effective C++ 條款 12:複製對象務必完整拷貝所有成員與基類部分

     編輯:關於C++

核心原則

設計良好的面向對象系統將對象內部封裝,僅暴露拷貝構造函數與拷貝賦值運算符(統稱 copying 函數)供外部複製對象。編譯器合成版本會逐一拷貝所有非靜態成員變量;若自行聲明,必須確保:

  1. 拷貝所有 local 成員變量
  2. 調用所有 base class 的對應 copying 函數

基類部分的正確拷貝姿勢

基類成員多為 private,派生類無法直接訪問。必須在派生類的 copying 函數中顯式調用基類對應函數:

class Customer {
    string name;
public:
    Customer(const Customer& rhs) : name(rhs.name) {}
    Customer& operator=(const Customer& rhs) {
        name = rhs.name;
        return *this;
    }
};

class PriorityCustomer : public Customer {
    int priority;
public:
    PriorityCustomer(const PriorityCustomer& rhs)
        : Customer(rhs),          // 呼叫基類拷貝構造函數
          priority(rhs.priority) {}

    PriorityCustomer& operator=(const PriorityCustomer& rhs) {
        Customer::operator=(rhs); // 呼叫基類拷貝賦值運算符
        priority = rhs.priority;
        return *this;
    }
};

避免 Copying 函數互相調用

  • 拷貝構造函數調用拷貝賦值運算符:邏輯錯誤,構造函數用於初始化「原始內存」,賦值運算符用於覆蓋「已構造對象」。
  • 拷貝賦值運算符調用拷貝構造函數:同樣不合理,會導致重複構造或資源洩漏。

消除代碼重複的正確做法

將共同邏輯提煉至私有輔助函數(常命名為 init 或 copyFrom),由兩個 copying 函數共同調用:

class Widget {
    // ...
private:
    void copyFrom(const Widget& rhs) {
        // 複製所有成員、基類部分
    }
public:
    Widget(const Widget& rhs) { copyFrom(rhs); }
    Widget& operator=(const Widget& rhs) {
        if (this != &rhs) copyFrom(rhs);
        return *this;
    }
};

關鍵提醒

Copying 函數必須確保複製「對象內所有成員變量」及所有「基類部分」。
切勿嘗試以某個 copying 函數實現另一個。應將共同功能放入第三個函數,由兩者共同調用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved