Effective C++——》条款12:复制对象时勿忘其每一部分

这句话包含两部分的意思:第一部分是要考虑到所有成员变量特别是后加入的,相应的拷贝构造函数和赋值运算符要及时更新;第二部分是在存在继承时不要遗忘基类部分的复制。先看第一部分的意思,举个例子:

复制代码
1 class SampleClass
2 {
3 private:
4          int a;
5 public:
6          SampleClass(const SampleClass& s):a(s.a)
7          {}
8 };
复制代码

这里只举了一个拷贝构造函数的例子,赋值运算符与之类似,如果这个时候又加了一个成员变量,比如double b,拷贝构造函数和赋值运算符就要相应地更新(构造函数当然也要更新,只是构造函数一般不会被忘记,而拷贝构造函数和赋值运算符却常常被遗忘)。像这样:

复制代码
1 class SampleClass
2 {
3 private:
4          int a;
5          double d;
6 public:
7          SampleClass(const SampleClass& s):a(s.a),d(s.d)
8         {}
9 };
复制代码

再看第二部分的意思,当存在继承关系时:

复制代码
1 class Derived: public SampleClass
2 {
3 private:
4          int derivedVar;
5 public:
6          Derived(const Derived& d):derivedVar(d.derivedVar){}
7 };
复制代码

像这样,很容易就会漏掉基类的部分,导致基类部分没有得到正常的拷贝,应该修改为如下:

复制代码
1 class Derived: public SampleClass
2 {
3 private:
4          int derivedVar;
5 public:
6          Derived(const Derived& d):SampleClass(d), derivedVar(d.derivedVar){}
7 };
复制代码

对于赋值运算符的重载,应该写成这样:

复制代码
1 Derived& operator=(const Derived& d)
2 {
3          SampleClass::operator=(d);
4          derivedVar = d.derivedVar;
5          return *this;
6 }
复制代码

可以看到,赋值运算符重载与拷贝构造函数的代码具有很高的相似性,但书上说“不要尝试以某个copying函数实现另一个copying函数”。我觉得这里有争议,上一个条款中,书上已经做到了在赋值运算符中调用拷贝构造函数了,像这样:

复制代码
1 Derived& operator=(const Derived& d)
2 {
3          Derived tmp(d);
4          swap(*this, tmp);
5          return *this;
6 }
复制代码

这就是一个在赋值运算符内调用拷贝构造函数的例子,也许在有些情况下,它的效率看上去不那么高,但却为代码的一致性提供了很好的保障,也能有效提供异常安全性。所以,在这个地方,我不大认同书上所说的,如果你有什么想法,可以留言共同讨论。书上所说的定制一个共有的private函数,比如init(),分别在拷贝构造函数和operator=中调用当然也是可以的。

最后总结一下:

Copying函数应该确保复制“对象内的所有成员变量”“所有基类成分”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值