Effective C++_笔记_条款12_复制对象时勿忘其每一个成分
(整理自Effctive C++,转载请注明。整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/)
编译器会在必要时候为我们的classes创建copying函数,这些“编译器生成版”的行为:将被烤对象的所有成员变量都做一份拷贝。
如果你声明自己的copying函数,意思就是告诉编译器你并不喜欢缺省实现中的某些行为。编译器仿佛被冒犯似的,会以一种奇怪的方式回敬:当你的实现代码几乎必然出错时却不告诉你。所以自己实现copying函数时,请遵循一条规则:如果你为class添加一个成员变量,你必须同时修改copying函数(你也需要修改class的所有构造函数以及任何非标准形式的operator=)。如果你忘记,编译器不太可能提醒你。
但是也要注意,一旦发生继承,可能会造成此一主题最暗中肆虐的一个潜藏危机。试考虑:
1: class PriorityCustomer:public Customer{
2: public:
3: ...
4: PriorityCustomer( const PriorityCustomer& rhs) ;
5: PriorityCustomer& operator=( const PriorityCustomer& rhs ) ;
6: ...
7: private:
8: int priority ;
9: };
10:
11: PriorityCustomer::PriorityCustomer( const PriorityCustomer& rhs )
12: :priority(rhs.priority)
13: {
14: logCall("PriorityCustomer copy constructor" ) ;
15: }
16:
17: PriorityCustomer& PriorityCustomer::operator= ( const PriorityCustomer& rhs )
18: {
19: logCall("PriorityCustomer copy assignment operator ");
20: priority = rhs.priority ;
21: return *this ;
22: }
我们可以看到,PriorityCustomer的copying函数看起来好像复制了PriorityCustomer的每一样东西。是的,它们复制了PriorityCustomer声明的成员变量,但每个PriorityCustomer还内含它所继承的Customer成员变量复件,而那些成员变量却未被复制。PriorityCustomer的copy构造函数并没有指定实参传给其base class构造函数,因此PriorityCustomer对象的Customer成分会被不带实参之Customer构造函数(即default构造函数---必定有一个否则无法通过编译)初始化。default构造函数对base class 成分执行缺省的初始化动作。
以上事态在PriorityCustomer的copy assignment操作符身上只有轻微不同。它不曾企图修改其base class的成员变量,所以那些成员变量保持不变。
任何时候只要你担负起“为derived class撰写copying函数”的重大责任,必须很小心地赋值其base class成分。那些成分往往是private,所以你无法直接访问它们,你应该让derived class的copying函数调用相应的base class函数:
1: PriorityCustomer:PriorityCustomer( const PriorityCustomer& rhs )
2: :Customer(rhs), //调用base class的copy构造函数
3: priority(rhs.priority)
4: {
5: logCall( "PriorityCustomer copy constructor " ) ;
6: }
7:
8: PriorityCustomer&
9: PriorityCustomer::operator=( const PriorityCustomer& rhs )
10: {
11: logCall("PriorityCustomer copy assignment operator") ;
12: Customer::operator=(rhs) ; //对base class成分进行赋值动作
13: priority = rhs.priority ;
14: return *this ;
15: }
本条款题目所说的“复制每一个成分”现在应该说的很清楚了。当你编写一个copying函数,请确保(1)复制所有local成员变量,(2)调用所有base class内适当的copying函数。
另外,如果你发现你的copy构造函数和copy assignment操作符有相近的代码,消除重复代码的做法是,建立一个新的成员函数供两者调用。这样的函数往往是private且常被命名为init。这个策略可以安全消除copy构造函数和copy assignment操作符之间的代码重复。
不要令某个copying函数调用另一个copying函数:令copy assignment操作符调用copy构造函数是不合理的,因为这试图构造一个已经存在的对象。反方向—令copy构造函数调用copy assignment操作符—同样无意义。构造函数用来初始化新对象,而assignment操作符只施行于已初始化对象身上。
请记住:
(1)Copying函数应该确保复制“对象内的所有的成员变量”及“所有base class成分”。
(2)不要尝试以某个copying函数实现另一个copying函数。应该将共同机能放在第三个函数中,并有两个copying函数共同调用。
Effective C++_笔记_条款12_复制对象时勿忘其每一个成分的更多相关文章
- EC读书笔记系列之7:条款12 复制对象时勿忘其每一个成分
记住: ★copying函数应确保复制“对象内的所有成员变量”及“所有base class成分” ★不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两 ...
- Effective C++ -----条款12: 复制对象时勿忘其每一个成分
Copying函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两个cop ...
- EC笔记:第二部分:12、复制对象时勿忘其每一个成分
EC笔记:第二部分:12.复制对象时勿忘其每一个成分 1.场景 某些时候,我们不想使用编译器提供的默认拷贝函数(包括拷贝构造函数和赋值运算符),考虑以下类定义: 代码1: class Point{ p ...
- Effective C++ 条款12:复制对象时勿忘其每一个成分
void logCall(const std::string& funcName); class Customer { public: ... Customer (const Customer ...
- [Effective C++ --012]复制对象时勿忘其每一个成分
引言: 在深拷贝和浅拷贝的理解中,我们知道了“拷贝构造函数”一词,并且也了解了它的构成. A(const A& r); // 形式有多种,在这里只列出一个 因此,在值传递的应用场景里,我们可以 ...
- 条款12:复制对象时勿忘其每一个成分(Copy all parts of an object)
NOTE: 1.Copying 函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 2.不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个 ...
- C++复制对象时勿忘每一部分
现看这样一个程序: void logCall(const string& funcname) //标记记录 { cout <<funcname <<endl; } cl ...
- Effective C++ 条款11,12 在operator= 中处理“自我赋值” || 复制对象时不要忘记每一个成分
1.潜在的自我赋值 a[i] = a[j]; *px = *py; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象, ...
- Java编程思想_笔记_第二章_一切都是对象
第二章对于知识只是点到,会在以后章节会详细展开. 笔记的侧重会偏向记录自己知识模糊的地方.比如 xxx 很重要很难很实用,但是已经熟练使用就没有记录,而 “使用对象.成员名称来使用成员变量”,较简单而 ...
随机推荐
- 由zImage生成uImage
一.手动使用mkimage命令 mkimage -A arm -O linux -T kernel -C none -a 30007fc0 -e 30007fc0 -n uImage -d /wo ...
- php 学习笔记 数组3
15.使用数组 1).并集(union) array_merge(array1,array2,array3..) 函数把两个或多个数组合并为一个数组,后面覆盖前面 2). 交集(intersecti ...
- 在Windows下github展示代码
最近大爱Web编程,于是寻找各种代码中,然后就发现了GitHub这个网站,如果你知道Google Code,那么你就知道这个GitHub是做什么的了.不过GitHub主要是用作基于Git的分布式版本管 ...
- Miller_Rabin、 Pollard_rho Template
Multiply and pow Function: //计算 (a*b)%c. a,b都是ll的数,直接相乘可能溢出的 // a,b,c <2^63 ll mult_modq(ll a,ll ...
- XMPP 服务器 Openfire 的 Emoji 支持问题(进行部分修改)
当前最新版3.9.3已经可以支持Emoji ----------------------------------------------------------------------------- ...
- 零成本建立的.NET小组开发平台
前言 说道.NET开发平台,首先想到的就是Visual Studio,建立.NET小组开发平台自然首推TFS.但其花费却也是相当昂贵的(当然在本国可以无视这些成本),近期的开发中接触到一些开源软件并读 ...
- (Relax njuptoj)1009 数的计算(DP)
其实DP 的关键在于找到子问题的结构. 我们规定arr[i][j]为在j左边填写i时的数的个数,很明显: arr[i][j]=a[0][i]+a[1][i]+...+arr[i/2][i](i&l ...
- m2eclipse简单使用,创建Maven项目 ,运行mvn命令(转)
前面介绍了如何安装m2eclipse,现在,我们使用m2ecilpse导入Hello World项目. 选择菜单项File,然后选择Import,我们会看到一个Import对话框,在该对话框中选择Ge ...
- 扩展 Windows Azure 运营能力 – 巴西
今天早些时候,在巴西圣保罗的一个活动上,我宣布了我们将在巴西设立一个 Windows Azure 区域数据中心的计划.我们希望该区域中心可以在 2014 年年初上线,并且我们很高兴地宣布将在未来 4 ...
- poll系统调用的内核态实现机制分析
版权所有,转载请标明出处 All right reserved,Copyright by 徐行而至 浅唱而归 前面已经比较详尽的分析了系统调用引发的内核执行过程,本文将继续分析一下linux2.6 ...