effective C++ 读书笔记 条款12
来源:互联网 发布:java高级流和低级流 编辑:程序博客网 时间:2024/05/16 07:37
条款12 : 复制对象时不要忘记其每一个成分
编写一个类用来表现顾客,其中手动写出copying函数使得外界对它们的调用记录会被logged下来:
#include <iostream>#include <string>using namespace std;void logCall(const string funcName){cout<<funcName<<endl;}class Customer{public:Customer(){}Customer(const Customer& rhs);Customer& operator= (const Customer& rhs);private:string name;};Customer::Customer(const Customer& rhs){this->name = rhs.name;logCall("拷贝构造函数");}Customer& Customer::operator=(const Customer& rhs){logCall("赋值操作符重载");name = rhs.name;return *this;}int main(){Customer c1;Customer c2(c1);Customer c3;c3 = c2;return 0;}
上面的函数看起来没有问题,知道一个新的成员变量加入:
#include <iostream>#include <string>using namespace std;void logCall(const string funcName){cout<<funcName<<endl;}class Date{};class Customer{public:Customer(){}Customer(const Customer& rhs);Customer& operator= (const Customer& rhs);private:string name;Date data; //这里增加一个成员变量};Customer::Customer(const Customer& rhs){//函数体并没有增加对data成员变量的处理,但是编译器不会给出任何警告this->name = rhs.name;logCall("拷贝构造函数");}Customer& Customer::operator=(const Customer& rhs){//函数体并没有增加对data成员变量的处理,但是编译器不会给出任何警告logCall("赋值操作符重载");name = rhs.name;return *this;}int main(){Customer c1;Customer c2(c1);Customer c3;c3 = c2;return 0;}/*如果你为一个class添加一个成员变量,你必须同时修改copying函数,如果你忘记,编译器是不会给出任何提示的。*/
上面说明:如果你为一个class添加一个成员变量,你必须同时修改copying函数
现在让他拥有子类:
#include <iostream>#include <string>using namespace std;void logCall(const string funcName){cout<<funcName<<endl;}class Date{};class Customer{public:Customer(){}Customer(const Customer& rhs);Customer& operator= (const Customer& rhs);private:string name;Date data; //这里增加一个成员变量};Customer::Customer(const Customer& rhs){//函数体并没有增加对data成员变量的处理,但是编译器不会给出任何警告this->name = rhs.name;logCall("拷贝构造函数");}Customer& Customer::operator=(const Customer& rhs){//函数体并没有增加对data成员变量的处理,但是编译器不会给出任何警告logCall("赋值操作符重载");name = rhs.name;return *this;}//现在发生了继承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的copying函数看起来好像复制了PriorityCustomer内的每一样东西,但是仔细看就会发现, 它们复制了PriorityCustomer声明的成员变量,但是每个PriorityCustomer还内含它所继承的Customer成员变 量复件(副本),而这些成员变量却没有被复制。priorityCustome的copy构造函数并没有制定实参传给其base class构造函数(也就是说它在它的成员初值列表中没有提到Customer),因此PriorityCustomer对象的Customer 成分会被不带实参的Customer构造函数初始化,那么也就是说Customer内的成员变量name和data将执行缺省的初始化。*/int main(){Customer c1;Customer c2(c1);Customer c3;c3 = c2;return 0;}/**/
子类的copy函数只是复制了子类本身加上去的成员变量,但是继承下来的成员变量却没有没复制,怎么解决?
#include <iostream>#include <string>using namespace std;void logCall(const string funcName){cout<<funcName<<endl;}class Date{};class Customer{public:Customer(){}Customer(const Customer& rhs);Customer& operator= (const Customer& rhs);private:string name;Date data; //这里增加一个成员变量};Customer::Customer(const Customer& rhs){//函数体并没有增加对data成员变量的处理,但是编译器不会给出任何警告this->name = rhs.name;logCall("拷贝构造函数");}Customer& Customer::operator=(const Customer& rhs){//函数体并没有增加对data成员变量的处理,但是编译器不会给出任何警告logCall("赋值操作符重载");name = rhs.name;return *this;}/*任何时候,只要我们为子类编写copy函数,那我们就必须小心复制其base class成分,而这些成分一般都是private;所以我们无法直接访问他们,我们能做的就是让子类的copying函数调用相应的base class函数:*/class PriorityCustomer:public Customer{public:PriorityCustomer(const PriorityCustomer& rhs);PriorityCustomer& operator= (const PriorityCustomer& rhs);private:int priority;};//我们能做的就是让子类的copying函数调用相应的base class函数:PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):Customer(rhs),priority(rhs.priority)//调用base class的copy构造函数{logCall("PriorityCustomer copy constructor");}//我们能做的就是让子类的copying函数调用相应的base class函数:PriorityCustomer& PriorityCustomer::operator =(const PriorityCustomer& rhs){logCall("PriorityCustomer copy assignment operator");Customer::operator =(rhs); //对base class成分进行赋值动作priority = rhs.priority;return *this;}int main(){Customer c1;Customer c2(c1);Customer c3;c3 = c2;return 0;}/**/
我们能做的就是让子类的copying函数调用相应的base class函数
总结:
1:Copying函数应该确保复制“对象内的所有成员变量”及所有base class成分
2:不要尝试以某个copying函数实现另外一个copying函数。应该讲共同的机能放进第三个函数当中,并由两个copying函数共同调用。
1 0
- 【Effective C++】读书笔记 条款13~条款17
- effective C++ 读书笔记 条款12
- 【Effective C++】读书笔记 条款49~51
- effective C++ 读书笔记 条款12与条款13
- 【Effective C++读书笔记】篇五(条款10~条款12)
- 【Effection C++】读书笔记 条款10~条款12
- 读书笔记《Effective C++》条款12:复制对象时勿忘其每一个成分
- 读书笔记: effective C++; 条款22 和 23, 尽量用传址少用传值。
- 读书笔记《Effective C++》条款03:尽可能使用const
- 读书笔记《Effective C++》条款13:以对象管理资源
- 读书笔记《Effective C++》条款19:设计class犹如设计type
- 读书笔记《Effective C++》条款27:尽量少做转型动作
- 读书笔记《Effective C++》条款30:透彻了解inlining的里里外外
- 读书笔记《Effective C++》条款42:了解typename的双重意义
- Effective C++ 读书笔记 条款一至三
- Effective C++ 读书笔记 条款01
- effective C++ 读书笔记 条款20
- effective C++ 读书笔记 条款21
- 自动生成IPv6列表
- Dijstra的greedy简单实现
- (转)《Java虚拟机原理图解》1.4 class文件中的字段表集合--field字段在class文件中是怎样组织的
- Java多线程(十)localthread
- 【iOS】UIImageView点击是现实高亮图,放手时现实默认图
- effective C++ 读书笔记 条款12
- 程序员到三十岁之后需要转行或者转管理吗
- Stanford
- URAL_2025_Line Fighting_均值不等式
- 二分查找
- 最大值和次大值(《编程珠玑(续)》第15章)
- 关于安卓串口编程的详解
- C++ memset详解
- VS2012版最常用的快捷键