[Effective C++ --006]若不能使用编译器自动生成的函数,就该明确拒绝
■本文内容■
□第一节 <引言>
在条款五的讲解中,我们已经知道编译器是聪明的家伙,它会帮助你生成类的构造函数、析构函数、一个copy构造函数和一个赋值运算符。
有时真的要感谢编译器所做的这一切,因为我们确实需要如此。但有的时候这一切又会给我们带来麻烦,本条款的介绍主题是麻烦的产生及如何解决。
□第二节 <案例:人员管理系统>
在一个人员管理系统中,有个class来描述每个人的信息是再合理不过的。
class PersonInfo{...};
那么下面的声明是合理的。
PersonInfo hanHan;
PersonInfo fangZhouZi;
那么下面的赋值也是合理的。
Person biaoGe(hanHan); // 用韩寒的信息拷贝出表哥--合理吗
hanHan = fangZhouZi; // 让韩寒成为方舟子--合理吗
显然,在现实中这些都是不合理的:要不违反伦理(克隆),要不目前的科技尚不能实现。对于编译器来说这没有什么不妥的地方。
所以我们要做的就是要让这逆天的情况永远不要发生。
□第三节 <寻找真凶>
好吧,也许写PersonInfo类的程序猿的本意并不是如此,但事实发生了就要找到真凶。其实,真凶也不难找到,就是那个自作聪明的编译器。
因为程序猿并没有声明Copy构造函数和Copy操作符。因为条款五中已经指出,如果你声明它们,而某些人尝试调用它们,编译器就会声明。
□第四节 <阻止犯罪>
如果在现实中,犯这么严重的罪,编译器肯定被抓去劳动改造了。既然不能给编译器判刑,那就要想个办法,防止它继续犯罪。
程序猿经过三天两夜的苦思冥想终于想到了一个自认为很好的方法。因为由编译器产生的函数都是public的,所以只要我自行定义它们,并且
以private修饰,那么编译器就不会生成它们了。但后来这个方法并不是绝对安全,因为成员函数和友元函数还是可以调用private函数的。
程序猿灵机一动:可以不实现这些函数啊。于是就有了下面的代码。
class PersonInfo {
public:
...
private:
PersonInfo(const PersonInfo&);
PersonInfo& operator=(const PersonInfo&);
};
再来看一下代码。private修饰符限定了只有成员函数和友元函数调用Copy函数和赋值运算符;而当真正调用的时候,由于未定义,连接器会报错。
程序猿是个好学生,他觉得错误可以在编译的阶段就被发现。事实上还真的被他找到了。于是他又写出了下面的代码。
class UnCopyable {
protected:
UnCopyable() {}
~UnCopyable() {}
private:
UnCopyable(const UnCopyable&);
UnCopyable& operator=(const UnCopyable&);
};
class PersonInfo : private UnCopyable {
...
};
再来看一下代码。只要任何人拷贝PersonInfo对象,编译器就会试着生成一个Copy构造函数和一个Copy操作符。
在尝试调用UnCopyable的对应的兄弟,很显然会被编译器毫不留情的拒绝:因为它们是private类型的。
到此,事情有了完美的结局,程序猿完美的避免了逆天的事再发生,编译器还是像以前一样尽职尽责。
■总结■
如果不需要编译器献的殷勤,就明确的拒绝它。拒绝的方式是可将相应的成员函数声明为private,并且不予实现。
或者像UnCopyable这样类也是一种做法,虽然会产生多重继承的问题。
目前该条准则在GUI项目中并没有发现有使用的地方。
(注:文中所用的人名、称呼等均不带有任何感情色彩,请勿对号入座!)
[Effective C++ --006]若不能使用编译器自动生成的函数,就该明确拒绝的更多相关文章
- 【Effective c++】条款6:若不想使用编译器自动生成的函数就应该明确拒绝
地产中介卖的是房子,其使用的中介软件系统应该有个类用来描述卖掉的房子 class HomeFoeSale { ......} 但是任何房子都是独一无二的,不应该存在两个房子拥有同样的属性,因此以下操作 ...
- Effective C++ 之 Item 6 : 若不想使用编译器自动生成的函数,就该明确拒绝
Effective C++ chapter 2. 构造 / 析构 / 赋值运算 (Constructors, Destructors, and Assignment Operators) Item 6 ...
- Effective C++ -----条款06:若不想使用编译器自动生成的函数,就该明确拒绝
为驳回编译器自动提供的功能,可将相应的成员函数声明为private并且不予实现. 使用像Uncopyable这样的base class也是一种做法(即先声明一个基类,然后私有继承它).这其实有点像使用 ...
- Effective C++学习笔记 条款06:如不想使用编译器自动生成的函数,就该明确拒绝
一.为驳回编译器自动提供的机能,可将相应成员函数声明为private并且不予实现.(如果你仅仅是自己不实现的话,编译器会帮你实现) 如: class A { public: A(const strin ...
- Effective C++_笔记_条款06_若不想使用编译器自动生成的函数,就该明确拒绝
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 通常如果你不希望class支持某一特定机能,只要不声明对应函数就 ...
- 读书笔记 effective c++ Item 6 如果你不想使用编译器自动生成的函数,你需要明确拒绝
问题描述-阻止对象的拷贝 现实生活中的房产中介卖房子,一个服务于这个中介的软件系统很自然的会有一个表示要被销售的房屋的类: class HomeForSale { ... }; 每个房产中介会立刻指出 ...
- Effective C++ 条款06:若不想使用编译器自动生成的函数,就该明确拒绝
规则一 将成员函数声明为private而且故意不实现他们 class HomeForSale { public: ... private: ... HomeForSale(const HomeForS ...
- Effective C++ 条款六 若不想使用编译器自动生成的函数,就该明确拒绝
class HomeForSale //防止别人拷贝方法一:将相应的成员函数声明为private并且不予实现 { public: private: HomeForSale(const HomeForS ...
- C++如何拒绝编译器自动生成的函数
每一个class,编译器都会自动生成四个特殊成员函数: destructor(析构函数) default constructor(默认构造函数) copy constructor(copy构造函数) ...
随机推荐
- linux tmp75 /dev/i2c-* 获取数据 demo
/********************************************************************** * linux tmp75 /dev/i2c-* 获取数 ...
- 上传文件出错:org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly
最近做一个web项目中有上传文件的功能,已经写出并在本地和部署到服务器上测试了好几个文件上传都没问题(我用的是tomcat).后来又上传了一个700多K的文件(前边的都是不足600K的,并且这个wor ...
- bug描述注意点
一个好的错误跟踪系统包括了错误的必要信息,如果做得不好,会造成迷惑,并误导读者.好的故障描述应该包括十个基本部分:标题.项目.所属模块.优先级.重要性.异常等级.可重复性.现象.操作过程和附件. ①标 ...
- as3 工具类分享 CookieMgr
今天分享一个工具类 CookieMgr,功能就是读取和写入 SharedObject 对象.很简单,都是静态方法,就不多说了 package org.polarbear.core { import f ...
- js基础第六天
获取节点属性 getAttribute("属性") 获取属性 setAttribute("属性","值"); 设置节点属性 删除某个属性 r ...
- [解决]Kali Linux DHCP自动获取IP失败 坑爹的VMWare桥接
root@kali:~# service networking restart [....] Running /etc/init.d/networking restart is deprecated ...
- 新手学习 Vim 的五个技巧
多年来,我一直想学 Vim.如今 Vim 是我最喜欢的 Linux 文本编辑器,也是开发者和系统管理者最喜爱的开源工具.我说的学习,指的是真正意义上的学习.想要精通确实很难,所以我只想要达到熟练的水平 ...
- SQL Where语句中AND与OR的计算次序 .
AND 用在where子句中,用来指示检索满足所有给定条件的行,而OR用在where子句中,用来指示检索匹配任一给定条件的行. Where子句中可包含任意数目的AND和OR操作符号,但是要注意在SQL ...
- 搭建Discuz! (mysql+apache+Discuz! )
0. 配置环境 0.0 安装apache 0.1 安装php 1.数据库准备 1.1 创建数据库用户 1.2 创建discuz使用的数据库(编码:utf8-general-ci) 1.3 把1.2创建 ...
- windows 一个进程可以允许最大的线程数
默认情况下,一个线程的栈要预留1M的内存空间 而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程 但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小. 你也 ...