(整理自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_复制对象时勿忘其每一个成分的更多相关文章

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

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

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

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

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

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

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

    void logCall(const std::string& funcName); class Customer { public: ... Customer (const Customer ...

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

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

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

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

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

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

  8. Effective C++ 条款11,12 在operator= 中处理“自我赋值” || 复制对象时不要忘记每一个成分

    1.潜在的自我赋值     a[i] = a[j];     *px = *py; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象, ...

  9. Java编程思想_笔记_第二章_一切都是对象

    第二章对于知识只是点到,会在以后章节会详细展开. 笔记的侧重会偏向记录自己知识模糊的地方.比如 xxx 很重要很难很实用,但是已经熟练使用就没有记录,而 “使用对象.成员名称来使用成员变量”,较简单而 ...

随机推荐

  1. Android studio多个项目之间怎么实现快速切换?

    Android studio多个项目之间怎么实现快速切换?Android studio中打开的项目太多了,想切换到一个项目很麻烦,怎么才能快速切换到另一个项目中呢?请看下文详细介绍 在对Android ...

  2. Oracle基础(五):多表查询

    一.多表查询 (一)简单多表查询 1.多表查询的机制 1)SQL: SELECT * FROM emp; --14条记录 SELECT * FROM dept;--4条记录 SELECT * FROM ...

  3. QTP实践总结

    QTP实践总结 查询数据库修改freq 1.Testcasetable创建查询select * from testcasetable order by fseq desc 2.设计表-选项-修改自动递 ...

  4. House Robber 分类: leetcode 算法 2015-07-09 20:53 2人阅读 评论(0) 收藏

    DP 对于第i个状态(房子),有两种选择:偷(rob).不偷(not rob) 递推公式为: f(i)=max⎧⎩⎨⎪⎪{f(i−1)+vali,f(i−2)+vali,robi−1==0robi−1 ...

  5. Inter IPP 跟 Microsoft V100编译器区别

    最近做项目用了两个编译器,由于是一种精度的算法计算,对计算的精度要求非常高,同时都用的float型,发现inter的结果比vs的结果好许多.但是不知道是什么原因,最后测试发现,是两个编译器的问题.   ...

  6. 【转】增强 scite 编辑器的代码提示功能

    在 windows 下写 Lua, 我能找到的最好的编辑器就是 luaForWindows 项目里带的 scite. npp (即 notepad++ ) 也将就着能用, 不过只有代码高亮和简单的单词 ...

  7. oracle 表复制

    1. 复制表结构及其数据: create table table_name_new as select * from table_name_old 2. 只复制表结构: ; 或者 create tab ...

  8. 一、Mongo的安装

    注:学习为主,平台为WIN7 32位系统 一.Mongo的安装 1.1 下载 到官方下载地址(http://www.mongodb.org/downloads)去下载所需要的版本 1.2 安装与运行 ...

  9. java模拟实现生产者---消费者问题

    本文章为小编原创,请尊重文章的原创性,转载请注意写明转载来源:http://blog.csdn.net/u012116457 已知技术參数: 生产者消费者问题,描写叙述一组生产者向一组消费者提供产品/ ...

  10. (step6.1.5)hdu 1233(还是畅通工程——最小生成树)

    题目大意:输入一个整数n,表示有n个村庄,在接下来的n*(n-1)/2中,每行有3个整数beigin.end.weight,分别表示路的起始村庄,结束村庄和村庄之间的距离. 求索要修的路的最短距离 解 ...