读书笔记《Effective C++》条款06:若不想使用编译器自动生成的函数,就该明确拒绝

所有编译器产出的函数都是public。如果不想让编译器自动生成这些函数,得自行声明它们,可以将copy构造函数或copy assignment操作符声明为private,这样就阻止了编译器暗自创建的版本,而且令这些函数为private,得以成功阻止人们调用它们。

一般而言这个做法并不绝对安全,因为member函数和friend函数还是可以调用private函数。有种办法:只声明这些private函数,但并不去定义。那么如果某些人不不慎调用任何一个,都将会得到一个链接错误。“将成员函数声明为private而且故意不实现它们”这一伎俩是如此为大家接受,因而被用在C++ iostream程序库中阻止copying行为。

例子:

class HomeForSale {
public:
	HomeForSale() {
	}
private:
	HomeForSale(const HomeForSale& rhs);//只有声明,没有定义
	HomeForSale& operator=(const HomeForSale& rhs);//只有声明,没有定义
};

HomeForSale h1;
HomeForSale h2;
HomeForSale h3(h1);//企图拷贝h1,使用private copy构造函数,编译不通过
h1 = h2;//使用private assignment操作符,编译不通过

上述class定义,当用户企图拷贝HomeForSale对象,编译器会阻挠他。如果不慎在member函数或friend函数之内那么做,就会轮到连接器发生报错。

将连接器错误编译移直编译器是可能的(而且那是好事,毕竟越早侦测出错误越好),只要将copy构造函数和copy assignment操作符声明为private就可以办到,但不是在HomeForSale自身,而是在一个专门为了阻止copying动作而设计的base class内。这个base class非常简单:

class Uncopyable {
protected:
	Uncopyable() {}	//允许derived对象构造和析构
	~Uncopyable() {}
private:
	Uncopyable(const Uncopyable&);	//但阻止copy
	Uncopyable& operator=(const Uncopyable&);
};

为求阻止HomeForSale对象被拷贝,我们唯一需要做的就是继承Uncopyable:

class HomeForSale : private Uncopyable {
//class不再声明copy构造函数或copy assignment操作符
};

这样,只要任何人——甚至是member函数或friend函数——尝试拷贝HomeForSale对象,编译器便试着生成一个copy构造函数和一个copy assignment操作符,但这些函数的“编译器生成版”会尝试调用其base class的对应兄弟,那些调用会被编译器拒绝,因为其base class的拷贝函数是private。

Uncopyable class的实现和运用颇为微妙,包括不一定得以public继承它,以及Uncopyable的析构函数不一定得是virtual等等。Uncopyable不含数据,符合empty base class optimization资格。但由于它总是扮演base class,因此使用这项技术可能导致多重继承,因为你往往还可能需要继承其他class,而多重继承有时会阻止empty base class optimization。通常你可以忽略这些微妙点,只要像上面那样使用Uncopyable,因为它能够正常运作。也可以使用Boost提供的版本:noncopyable。


要点:

为阻止编译器自动(暗自)提供的机能,可将相应的成员函数声明为private并且不予实现。使用像Uncopyable这样的base class也是一种做法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值