EffectiveC++ 第2章 构造/析构/赋值运算
我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的“可能比较准确”的「翻译」。
Chapter 2 构造 / 析构 / 赋值
条款 05:了解C++ 默默编写并调用哪些函数
如果你写下:
class Empty{ };
事实上编译器会帮你补全:
class Empty{
public:
Empty() { }
Empty(const Empty& rhs) { }
~Empty() { }
Empty& operator=(const Empty& rhs) { }
} ;
这些函数只有被需要时才会被创建出来
默认构造函数只是单纯的将来源对象每个non-static成员变量拷贝到目标对象
条款 06: 若不想使用编译器自动生成的函数,就改明确拒绝
将拷贝构造函数和赋值重载函数显式声明为private吧
但有一个小缺陷,就是member函数和友元函数依然可以访问,但是会造成连接错误(linkage error)
编译的话连接器会报错
条款07: 为多态基类声明 virtual析构函数
不作为基类的类不要声明虚析构函数
有继承关系的基类一定加上virtual析构函数(带多态性质的base class)
pure virtual纯虚构函数: virtual ~XXX() = 0;
条款 08: 别让异常逃离析构函数
如果客户需要对某个函数运行期间抛出的异常作出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作
条款 09: 绝不在构造和析构过程中调用virtual 函数
若是有两个有继承关系的类,主类有一个virtual函数,并在构造函数里调用;子类定义了另一个版本的此函数,当在main里构造此子类对象时,实际上还是先调用基类的构造函数,然而基类构造函数调用的virtual
函数版本实际上还是基类的。若此函数会使用子类里的元素,然而之类成员都还未初始化,就会引发错误
当类中有多个构造函数,它们兴许有共同的部分。有一种较为出色的做法是定义一个void类型的init函数,然后将初始化中需要调用的函数放在里面,将init单独放在构造函数里就好了。
综上,在构造和析构期间不要调用虚函数,因为这类调用从不下降至derived class
条款 10: 令 operator= 返回一个 reference to *this
int x,y,z;
x = y = z = 15;
根据右结合律,可以解释为x = (y = (z = 15));
为了实现连锁赋值,赋值操作赋必须返回一个reference指向操作符左侧实参:
class Widget{
public:
…
Widget& operator=(const Widget& rhs){
…
return *this;
}
};
此标准适用于所有与赋值相关运算
条款 11:在 operator=中处理自我赋值
类对象的赋值,看下面一种情况:
class Widget{
…
private:
Bitmap* pb;
};
Widget& Widget::operator=(const Widget& rhs)
{
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
存在的问题是,如果*this和rhs是同一个对象,delete操作会同时删除两者的bitmap。可以这样操作:
Widget& Widget::operator=(const Widget& rhs)
{
if(this==&rhs) return *this; //如果是自我赋值则不做任何事
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
条款 12: 复制对象时勿忘其每一个成分
如果对于拷贝函数,你的复制成员没有写全,编译器是不会报错的,因为这符合逻辑。所以记得将需要拷贝的成员变量都放进copying函数
另外,当手动撰写继承类的copying函数时,一定记得在初始化列表复制其base class的成分.否则在复制构造函数中base class成分会由base class的default构造函数初始化,而copy assignment函数根本不会管base class的成分
可以这样写:(A extends B)
在copy函数中:
A::A(const A& rhs):B(rhs)
{
……
}
在copy assignment函数中:
A& A::operator=(const A& rhs)
{
if(this==&rhs)
return *this;
B::operator=(rhs); //对base class成分进行赋值动作
……
return *this;
}
现在很清楚了,当你编写一个copying函数,请确保(1)复制所有local成员变量(2)调用所有base classes内适当的copying函数
OVER
EffectiveC++ 第2章 构造/析构/赋值运算的更多相关文章
- 《Effective C++》第2章 构造/析构/赋值运算(2)-读书笔记
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...
- 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...
- Effective C++ —— 构造/析构/赋值运算(二)
条款05 : 了解C++默默编写并调用哪些函数 编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 1. default构造函 ...
- Effective C++ 笔记二 构造/析构/赋值运算
条款05:了解C++默默编写并调用哪些函数 编译器默认声明一个default构造函数.一个copy构造函数.一个copy assignment操作符和一个析构函数.这些函数都是public且inlin ...
- Effective C++笔记:构造/析构/赋值运算
条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...
- Effective C++ -- 构造析构赋值运算
05.了解C++默默编写并调用哪些函数 编译产生的析构函数时non-virtual,除非这个类的基类析构函数为virtual 成员变量中有引用和const成员时,无法自己主动生成copy assign ...
- Effective C++笔记(二):构造/析构/赋值运算
参考:http://www.cnblogs.com/ronny/p/3740926.html 条款05:了解C++默默编写并调用哪些函数 如果自定义一个空类的话,会自动生成默认构造函数.拷贝构造函数. ...
- 【Effective C++】构造/析构/赋值运算
条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...
- Effective C++ 2.构造 析构 赋值运算
//条款07:为多态基类声明virtual析构函数 // 1.若基类的析构函数不定义为虚函数,由于基类的指针或引用可以指向派生类的对象,则在删除基类对象的时候可能会出错,导致破坏数据结构. // 2. ...
随机推荐
- Django contenttypes 组件
contenttypes组件 介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Conte ...
- 【Python 25】52周存钱挑战5.0(datetime库和import)
1.案例描述 按照52周存钱法,存钱人必须在一年52周内,每周递存10元.例如,第一周存10元,第二周存20元,第三周存30元,直到第52周存520元. 记录52周后能存多少钱?即10+20+30+. ...
- Nginx解读内置非默认模块 ngx_http_stub_status_module
1 Background http://nginx.org/en/docs/http/ngx_http_stub_status_module.html ngx_http_stub_status_mod ...
- 【js】this问题
var obj = { a: 10, b: () => { console.log(this.a); // undefined console.log(this); // Window {pos ...
- Jetson TX2(1)ubutu1604--安装Nvidia Linux驱动
https://www.jianshu.com/p/c8ebe4aaa708 系统开机首次进入的是以nvidia用户登录的Ubuntu 命令行界面.Nvidia 驱动安装 通过sudo su 输入密码 ...
- 静态代理与JDK动态代理
demo地址: https://github.com/ZbLeaning/leaning 代理: 为其他对象提供一种代理以控制对这个对象的访问.分为静态代理和动态代理.代理模式的目的就是为真实业务对象 ...
- 故障公告:docker swarm集群“群龙无首”造成部分站点无法访问
今天傍晚 17:38-18:18 左右,由于 docker swarm 集群出现 "The swarm does not have a leader" 问题,造成博问.闪存.园子. ...
- Jquery mobile动态生成ListView调用刷新方法报错
错误:cannot call methods on listview prior to initialization... 示例: <div data-role="page" ...
- JMeter配置好环境变量后无法启动---翻车笔记
双击jmeter.bat出现下图情况 手欠了win7中配置 path无意中多删了变量 解决方法:在计算机-属性-高级系统设置-环境变量Path中添加 %SystemRoot%/system32;%Sy ...
- php函数 array_diff
array_diff ( array $array1 , array $array2 [, array $... ] ) : array 对比 array1 和其他一个或者多个数组,返回在 array ...