[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构造函数) ...
随机推荐
- @Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction区别 .(转)
mvc renderaction renderpartial 杂谈 Html.RenderPartial与Html.RenderAction这两个方法都是用来在界面上嵌入用户控件的. ...
- pl/sql developer 编码格式设置
pl/sql developer编码格式设置 一.pl/sql developer 中文字段显示乱码 原因:因为数据库的编号格式和pl /sql developer的编码格式不统一造成的. 二. ...
- Spring 教程(一)
一.Spring是什么 通常说的Spring其实指的是Spring Framework,它是Spring下的一个子项目,Spring围绕Spring Framework这个核心项目开发了大量其他项目, ...
- 学习xcode 博客
csdn http://blog.csdn.net/tianyitianyi1/article/category/1160169/2
- codeforces 676D Theseus and labyrinth BFS搜索
分析:一个n*m的矩阵,每个格子有12个状态,每次按一次,每个格子转90度,所以整个矩阵只有4种状态,然后爆搜就好了 #include <cstdio> #include <iost ...
- 面向对象(class0420)
测试 交换两个变量的值 int num1 = 5;int num2=6; 通过程序交换让num1 = 6,num2=5; 求两个数的最大值 (求三个数最大值) 求1-100之间所有奇数的和 找胖子,{ ...
- 企业移动互联网O2O微信支付流程图
过去一周里最受关注的应该就是微信了,腾讯合作伙伴大会微信分论坛的火爆现场,没有亲临其境是无法想象的,近3000人报名,2000多人来到现场,试图进入只能容纳300人的会场…… 闲话不表,进入正题吧,本 ...
- HDU-4704 Sum 大数幂取模
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4704 题意:求a^n%m的结果,其中n为大数. S(1)+S(2)+...+S(N)等于2^(n-1) ...
- 二叉搜索树算法详解与Java实现
二叉查找树可以递归地定义如下,二叉查找树或者是空二叉树,或者是满足下列性质的二叉树: (1)若它的左子树不为空,则其左子树上任意结点的关键字的值都小于根结点关键字的值. (2)若它的右子树不为空,则其 ...
- 关于 Java 对象序列化您不知道的 5 件事
数年前,当和一个软件团队一起用 Java 语言编写一个应用程序时,我体会到比一般程序员多知道一点关于 Java 对象序列化的知识所带来的好处. 关于本系列 您觉得自己懂 Java 编程?事实上,大多数 ...