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

编译器会在必要的时候为我们的类创建copy构造函数和赋值函数,并且将被拷贝对象的所有成员变量都做一份拷贝。如果你声明自己的copy构造函数和赋值函数,意思就是告诉编译器你并不喜欢缺省实现中的某些行为。

考虑一个class用来表现顾客,其中自己写出copying函数,使得外界对它们的调用会被日志记录下来:

void logCall(const std::string& value);//日志记录
class Customer{
public:
    ...
    Customer(const Customer& rhs);
    Customer& operator=(const Customer& rhs);
private:
    std::string m_name;
};

Customer::Customer(const Customer& rhs):m_name(rhs.m_name)
{
   logCall("Customer copy constructor");
}
Customer& Customer::operator=(const Customer& rhs)
{
   logCall("Customer copy assignment operator");
   m_name = rhs.m_name;
   return *this;
}

这里的每一件事情都很好,直到另一个成员变量的出现:

class Date{...};
class Customer{
public:
    ...//同上
private:
    std::string m_name;
    Date m_date;
};

这时候既有的copying函数执行的是局部拷贝,它们的确复制了m_name,但没有复制新添加的m_date。所以,如果你为class添加了一个成员变量,你必须同时修改copying函数,以及任何非标准形式的operator=,如果你忘记了,编译器不太可能提醒你。

一旦发生继承,可能会造成一个潜藏的危机,试考虑:

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

ChildCustomer::ChildCustomer(const ChildCustomer& rhs):m_priority(rhs.m_priority)
{
   logCall("ChildCustomer copy constructor");
}
ChildCustomer& ChildCustomer::operator=(const ChildCustomer& rhs)
{
    logCall("ChildCustomer copy assignment operator");
    m_priority = rhs.m_priority;
    return *this;
}

ChildCustomer的copying函数复制了ChildCustomer声明的成员变量,但每个ChildCustomer内还含有它继承的Customer成员变量的副本,而那先成员变量却未被复制。ChildCustomer的copy构造函数并没有指定实参传给其父类构造函数,因此ChildCustomer对象的Customer成分会被不带实参之Customer构造函数初始化。default构造函数将针对m_name和m_date执行缺省的初始化动作。

任何时候只要你承担起“为 子派生类撰写copying函数”的重责大任,你必须很小心地也复制其父类成分,那些成分往往是private,所以你无法直接访问它们,你应该让派生类的copying函数调用相应的父类函数

ChildCustomer::ChildCustomer(const ChildCustomer& rhs)
              :Customer(rhs),//调用父类的copy构造函数
              m_priority(rhs.m_priority)
{
   logCall("ChildCustomer copy constructor");
}
ChildCustomer& ChildCustomer::operator=(const ChildCustomer& rhs)
{
    logCall("ChildCustomer copy assignment operator");
    Customer::operator=(rhs);//调用父类成分进行赋值操作
    m_priority = rhs.m_priority;
    return *this;
}

请记住:

  • copying函数应该确保复制“对象内的所以成员变量”及“所有父类成分”。
  • 不要尝试以某个copying函数实现另一个copying函数。应该将共同代码部分放进第三个函数中,并由两个copying函数共同调用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值