■本文内容■
□第一节 <引言>
在条款五的讲解中,我们已经知道编译器是聪明的家伙,它会帮助你生成类的构造函数、析构函数、一个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]若不能使用编译器自动生成的函数,就该明确拒绝的更多相关文章

  1. 【Effective c++】条款6:若不想使用编译器自动生成的函数就应该明确拒绝

    地产中介卖的是房子,其使用的中介软件系统应该有个类用来描述卖掉的房子 class HomeFoeSale { ......} 但是任何房子都是独一无二的,不应该存在两个房子拥有同样的属性,因此以下操作 ...

  2. Effective C++ 之 Item 6 : 若不想使用编译器自动生成的函数,就该明确拒绝

    Effective C++ chapter 2. 构造 / 析构 / 赋值运算 (Constructors, Destructors, and Assignment Operators) Item 6 ...

  3. Effective C++ -----条款06:若不想使用编译器自动生成的函数,就该明确拒绝

    为驳回编译器自动提供的功能,可将相应的成员函数声明为private并且不予实现. 使用像Uncopyable这样的base class也是一种做法(即先声明一个基类,然后私有继承它).这其实有点像使用 ...

  4. Effective C++学习笔记 条款06:如不想使用编译器自动生成的函数,就该明确拒绝

    一.为驳回编译器自动提供的机能,可将相应成员函数声明为private并且不予实现.(如果你仅仅是自己不实现的话,编译器会帮你实现) 如: class A { public: A(const strin ...

  5. Effective C++_笔记_条款06_若不想使用编译器自动生成的函数,就该明确拒绝

    (整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 通常如果你不希望class支持某一特定机能,只要不声明对应函数就 ...

  6. 读书笔记 effective c++ Item 6 如果你不想使用编译器自动生成的函数,你需要明确拒绝

    问题描述-阻止对象的拷贝 现实生活中的房产中介卖房子,一个服务于这个中介的软件系统很自然的会有一个表示要被销售的房屋的类: class HomeForSale { ... }; 每个房产中介会立刻指出 ...

  7. Effective C++ 条款06:若不想使用编译器自动生成的函数,就该明确拒绝

    规则一 将成员函数声明为private而且故意不实现他们 class HomeForSale { public: ... private: ... HomeForSale(const HomeForS ...

  8. Effective C++ 条款六 若不想使用编译器自动生成的函数,就该明确拒绝

    class HomeForSale //防止别人拷贝方法一:将相应的成员函数声明为private并且不予实现 { public: private: HomeForSale(const HomeForS ...

  9. C++如何拒绝编译器自动生成的函数

    每一个class,编译器都会自动生成四个特殊成员函数: destructor(析构函数) default constructor(默认构造函数) copy constructor(copy构造函数) ...

随机推荐

  1. 【Grunt】

    GRUNT The JavaScript Task Runnerhttp://gruntjs.com/ Grunt打造前端自动化工作流http://tgideas.qq.com/webplat/inf ...

  2. 【转】如何下载并编译Android4.0内核源码goldfish(图文)

    原文网址:http://blog.csdn.net/flydream0/article/details/7070392 关于如何下载Android4.0源码,请查看我的博客内另一篇文章(同样是图文教程 ...

  3. HTML入门基础教程相关知识

    HTML入门基础教程 html是什么,什么是html通俗解答: html是hypertext markup language的缩写,即超文本标记语言.html是用于创建可从一个平台移植到另一平台的超文 ...

  4. 在ASP.NET MVC中使用DropDownList

    在ASP.NET MVC中,尽管我们可以直接在页面中编写HTML控件,并绑定控件的属性,但更方便的办法还是使用HtmlHelper中的辅助方法.在View中,包含一个类型为HtmlHelper的属性H ...

  5. POJ 3377 Ferry Lanes

    虽然它出现在dp专场里···但是我第一反应是一道最短路题···不过幸好它出现在dp专场里···因为我不怎么会dijstra什么的··· 题意:一条河上有N+1对码头,每个相邻码头之间需要一定时间到达, ...

  6. [Everyday Mathematics]20150101

    (1). 设 $f(x),g(x)$ 在 $[a,b]$ 上同时单调递增或单调递减, 试证: \[ (b-a)\int_a^b f(x)g(x)\mathrm{\,d}x \geq \int_a^b ...

  7. BNU 51275 道路修建 Large 并查集

    分析(引入Q神题解  %%%Q) 如果使用可持久化并查集,二分答案判定连通性,复杂度是O(mlog3n),不能在时限内出解.考虑到并查集实际上是一棵树,可以尝试在边上维护一些信息,假设t时刻加了一条边 ...

  8. hive 配置mysql元数据库

    在 hive的配置文件hive-site.xml中 <?xml version="1.0"?> <!-- Licensed to the Apache Softw ...

  9. Cloudera Manager安装

    安装环境: 系统:CentOS 6.3 64位 虚拟机:VMWare

  10. .net之单元测试

    一.单元测试的目的是为了提高项目的质量 二..net单元测试的实施步骤是:在已经创建的类文件的某个方法上右键-->选择创建单元测试-->系统会创建单元测试解决方案--->单元测试解决 ...