Effective C++ 条款 12:复制对象时勿忘其每一个成分

发布于:2025-02-11 ⋅ 阅读:(29) ⋅ 点赞:(0)

条款 12:复制对象时勿忘其每一个成分

核心问题

  • 对象的完整性
    在实现复制操作(包括拷贝构造函数和赋值操作符)时,必须确保复制对象的所有成员变量和基类部分,否则可能导致对象不完整或行为异常。

  • 常见误区
    尝试通过一个复制函数(如拷贝构造函数)直接调用另一个复制函数(如赋值操作符)来简化逻辑。这种方法容易导致重复代码或遗漏某些成分。


示例:完整复制对象

实现拷贝构造函数和赋值操作符时,需分别处理成员变量和基类成分。

class Base {
protected:
  int baseValue;
public:
  Base(int val) : baseValue(val) {}
  Base(const Base& rhs) : baseValue(rhs.baseValue) {}  // 复制 Base 成分
  Base& operator=(const Base& rhs) {
    if (this != &rhs) {
      baseValue = rhs.baseValue;
    }
    return *this;
  }
};

class Derived : public Base {
private:
  std::string derivedValue;
public:
  Derived(int baseVal, const std::string& str) 
    : Base(baseVal), derivedValue(str) {}

  Derived(const Derived& rhs) 
    : Base(rhs), derivedValue(rhs.derivedValue) {}  // 调用 Base 的拷贝构造函数

  Derived& operator=(const Derived& rhs) {
    if (this != &rhs) {
      Base::operator=(rhs);             // 调用 Base 的赋值操作符
      derivedValue = rhs.derivedValue;  // 复制 Derived 成分
    }
    return *this;
  }
};

关键点:

  1. 成员变量复制:每个成员变量都需要在复制函数中被正确处理。
  2. 基类复制:显式调用基类的拷贝构造函数或赋值操作符,确保基类成分被完整复制。

示例:提取公共逻辑

为了避免重复代码,可以将共同逻辑提取到一个辅助函数中。

class Widget {
private:
  int id;
  std::string name;

  void copyFrom(const Widget& rhs) {
    id = rhs.id;
    name = rhs.name;
  }

public:
  Widget(int i, const std::string& n) : id(i), name(n) {}

  Widget(const Widget& rhs) {
    copyFrom(rhs);  // 使用公共函数处理复制逻辑
  }

  Widget& operator=(const Widget& rhs) {
    if (this != &rhs) {
      copyFrom(rhs);  // 避免重复代码
    }
    return *this;
  }
};

关键点:

  1. 提取公共逻辑到 copyFrom 函数,减少代码重复。
  2. 确保拷贝构造函数和赋值操作符调用相同的逻辑。

设计建议

  1. 完整性检查

    • 确保每个成员变量和基类成分都被正确复制。
  2. 避免重复代码

    • 提取共同逻辑到辅助函数,提高代码复用性。
  3. 基类与派生类

    • 派生类复制函数应显式调用基类的复制函数。

总结

  • 在实现复制操作时,确保对象的每一个成员变量和基类成分都被正确处理。
  • 避免重复代码,将复制逻辑提取到辅助函数中。
  • 始终遵循良好的设计原则,确保代码的可维护性和正确性。

网站公告

今日签到

点亮在社区的每一天
去签到