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 很重要很难很实用,但是已经熟练使用就没有记录,而 “使用对象.成员名称来使用成员变量”,较简单而 ...
随机推荐
- Cocos2dx项目移植Android平台
链接地址:http://blog.csdn.net/iuncle/article/details/24772183 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.Classes目录下存放. ...
- BZOJ 2101: [Usaco2010 Dec]Treasure Chest 藏宝箱( dp )
dp( l , r ) = sum( l , r ) - min( dp( l + 1 , r ) , dp( l , r - 1 ) ) 被卡空间....我们可以发现 l > r 是无意义的 ...
- 随手记今天跟的几个iOS项目代码的问题
休了一阵子假期,今天刚回来上班,项目代码已经有挺大的变化了,我就先体验.发现.跟进问题. 第一个问题是点击某个cell就挂掉的现象,同事表示必现但挺神奇.由于挂掉的时候没有啥有意义的信息,所以先简单粗 ...
- Android 中 关闭部分 Activity 的方法总结
每一个activity都有自己的生命周期,被打开了最终就要被关闭. 四种结束当前的activity方法 但如果已经启动了四个Activity:A,B,C和D, 在D Activity里,想再启动一个A ...
- js window.onload事件
1.最简单的调用方式 直接写到html的body标签里面,如: ? 1 2 3 4 <html> <body onload="func()"& ...
- IPython在Windows 7上的搭建步骤
安装篇 pip install jupyter 使用篇 启动本地notebook,打开Windows命令行,键入:ipython notebook
- Kruscal 、 Prime Template
Kruscal Template : 很裸的Kruscal Template(求最小生成树中最长路,即最短路中最长路) //#pragma comment(linker, "/STACK: ...
- Android HttpClient HttpURLConnection相关介绍
Android HttpClient HttpURLConnection相关介绍 遇到一个问题 在android studio上用HttpClient编写网络访问代码的时候,发现该类无法导入并使用.. ...
- OKR 方法 学习笔记
最近公司兴起了对OKR这个词的讨论,并且听到时总会伴随提到KPI,提到绩效考核.那OKR到底是什么呢?与KPI的区别在哪里?与绩效考核有什么关系?它与我们现在推行的敏捷开发有啥关系呢?因此,就到网上查 ...
- Poj 2777 Count Color(线段树基础)
又毁三观了.......虽然题目数据有坑:区间[a,b]可能会有a>b的情况,但是我一开始没有考虑它也能过. 此外莫名其妙的TLE #include <iostream> #incl ...