void logCall(const std::string& funcName);
class Customer {
public:
...
Customer (const Customer& rhs);
Customer& operator=(const Customer& rhs);
...
private:
std::string name;
};
Customer::Customer(const Customer& rhs) : name(rhs.anme) {
logCall("Customer copy constructor");
}
Customer& Customer::operator=(const Customer& rhs) {
logCall("Customer copy assignment operator");
name = rhs.name;
return *this;
}

以上看起来并没有任何问题,但是我们为它添加一个成员变量

class Date { ... };
class Customer {
public:
...
private:
std::string name;
Date lastTransaction;
}

我们添加了一个成员变量,如果我们在copying函数中没有对其进行赋值,编译器也不会报错,这个时候可能不是我们想要的结果。

class PriorityCustomer: public Customer {
public:
...
PriorityCustomer(const PriorityCustomer& rhs);
PriorityCustomer& operator=(const PriorityCustomer& rhs);
...
private:
int priority;
};
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):priority(rhs.priority) {
logCall("PriorityCustomer copy constructor");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs) {
logCall("PriorityCustomer copy assignment operator");
priority = rhs.priority;
return *this;
}

PriorityCustomer继承了Customer,而那些成员变量却未被赋值。但在构造PriorityCustomer之前,肯定调用了Customer构造函数(即default构造函数——必定有一个否则无法通过编译)初始化。default构造函数将指针对name和lastTransaction执行缺省的初始化动作。

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

PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs) : Customer(rhs),priority(rhs.priority) {
logCall("PriorityCustomer copy constructor");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs) {
logCall("PriorityCustomer copy assignment operator");
Customer::operator(rhs); // 对base class成分进行赋值动作
priority = rhs.priority;
return *this;
}

copy assignment和copy构造函数可能存在相同的代码,但是它们两者之间任何一个调用另外一个都是不合法的。

总结

  1. Copying函数应该确保复制”对象内的所有成员变量”及”所有base class成分”。
  2. 不要尝试以某个copying函数实现另外一个copying函数。应将共同机能放进第三个函数中,并有两个copying函数共同调用。

Effective C++ 条款12:复制对象时勿忘其每一个成分的更多相关文章

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

    Copying函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两个cop ...

  2. EC读书笔记系列之7:条款12 复制对象时勿忘其每一个成分

    记住: ★copying函数应确保复制“对象内的所有成员变量”及“所有base class成分” ★不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两 ...

  3. Effective C++_笔记_条款12_复制对象时勿忘其每一个成分

    (整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 编译器会在必要时候为我们的classes创建copying函数, ...

  4. EC笔记:第二部分:12、复制对象时勿忘其每一个成分

    EC笔记:第二部分:12.复制对象时勿忘其每一个成分 1.场景 某些时候,我们不想使用编译器提供的默认拷贝函数(包括拷贝构造函数和赋值运算符),考虑以下类定义: 代码1: class Point{ p ...

  5. 条款12:复制对象时勿忘其每一个成分(Copy all parts of an object)

    NOTE: 1.Copying 函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 2.不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个 ...

  6. [Effective C++ --012]复制对象时勿忘其每一个成分

    引言: 在深拷贝和浅拷贝的理解中,我们知道了“拷贝构造函数”一词,并且也了解了它的构成. A(const A& r); // 形式有多种,在这里只列出一个 因此,在值传递的应用场景里,我们可以 ...

  7. C++复制对象时勿忘每一部分

    现看这样一个程序: void logCall(const string& funcname) //标记记录 { cout <<funcname <<endl; } cl ...

  8. Effective C++(12) 复制对象时要复制每一个成员

    问题聚焦: 负责拷贝的两个操作:拷贝构造函数和重载赋值操作符. 一句话总结,确保被拷贝对象的所有成员变量都做一份拷贝. Demo   void logCall(const std::string&am ...

  9. Effective C++ 条款12

    复制对象时,勿忘其每个成分 作者在本节条款提醒我们,在多重继承的情况下进行copy或者copy assignment 的operator=的编写时,一定要考虑base 类部分数据的初始化后者复制. 对 ...

随机推荐

  1. 57、Design Support Library 介绍及环境搭建

    一.Material Design几个要素 扁平化.简洁: 水波反馈: 良好体验的过渡动画: 材料空间位置的直观变化: 二.Android Studio配置 在 build.gradle 文件中加入, ...

  2. manacher算法处理最长的回文子串(一)

    引言 相信大家都玩过折叠纸张,如果把回文串相当于折叠一个A4纸,比如ABCDDCBA就是沿着中轴线(D与D之间)对折重合,那么这个就是一个回文串.或者是ABCDEDCBA的中轴线就是E,那么沿着中轴线 ...

  3. 【BZOJ4566】[Haoi2016]找相同字符 后缀数组+单调栈

    [BZOJ4566][Haoi2016]找相同字符 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同 ...

  4. hdu 1159 Common Subsequence 【LCS 基础入门】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1159 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  5. Share and NTFS Permission

    NTFS Permissions Share Permissions Share and NTFS Permission Similarities 共享权限和NTFS权限的相似性 Modifying ...

  6. mysql utf8字符集下使用DES_ENCRYPT

    DES_ENCRYPT() 加密字符串后内容为空 改变字符集latin1  可以保存和解密(DES_DECRYPT)

  7. linux库冲突解决方法 apt purge / aptitude purge

    remove libs: [apt-get purge remove] or [aptitude purge] how to use apt-get and aptitude https://blog ...

  8. TCP原理

    1.http://coolshell.cn/articles/11564.html 2.http://coolshell.cn/articles/11609.html 3.一站式学习wireshark ...

  9. 基于UDP的套接字、粘包问题

    一.基于UDP的套接字 UDP服务端 ss = socket() #创建一个服务器的套接字 ss.bind() #绑定服务器套接字 inf_loop: #服务器无限循环 cs = ss.recvfro ...

  10. Java String.split() 使用注意

    java的split()方法用于字符串中根据指定的字符进行分割,得到的是一个字符串数组 public String[] split(String regex) Splits this string a ...