EffectiveC++详解:条款06-若不想使用编译器自动生成的函数,应该明确拒绝

本文详细介绍了如何在C++中避免编译器自动生成拷贝构造函数和拷贝赋值运算符,通过声明为private或使用C++11的删除特性,以及设计一个基类Uncopytable来确保在编译期间就能捕获到非法拷贝尝试。

@Author:CSU张扬
@Email:csuzhangyang@gmail.com or csuzhangyang@qq.com
@我的网站: https://www.cppbug.com

条款06-若不想使用编译器自动生成的函数,应该明确拒绝

独一无二的对象

“世界上没有两片相同的叶子”,我们定义一个类表示叶子 class Leaf { ... }。显然任何拷贝动作都是不合逻辑的:

Leaf l1;
Leaf l2;
Leaf l3(l1);  // 编译不通过
l1 = l2;      // 编译不通过

如果我们不声明 拷贝构造函数 和 拷贝赋值运算符,那么编译器会为我们生成一个。所以我们要声明这两个函数,但是我们却不能用。因此我们可以把这两个函数声明为 private

注意: C++11支持将构造函数声明为 删除的:

Leaf(const Leaf&) = delete;
Leaf& operator=(const Leaf&) = delete;

在编译期间发现错误

上节将拷贝构造函数 和 拷贝赋值运算符声明为 private,但是我们的成员函数和友元函数仍可以调用,这时会产生连接错误。我们要将连接期错误转移到编译期间,我们可以专门为阻止拷贝动作设计一个基类。

class Uncopytable {
protected:
    Uncopytable() { }
    ~Uncopytable() { }
private:
    Uncopytable(const Uncopytable&);
    Uncopytable& operator=(const Uncopytable&);
};

class Leaf : private Uncopytable {
    ... ...;
};

此时,以任何形式来拷贝 Leaf 对象,编译器就算给 Leaf 生成了拷贝构造函数,那么这个拷贝动作会调用基类的拷贝构造函数,这会被编译器拒绝。

此代码还有几个微妙的地方:

  1. Uncopytable 作为基类,析构函数是 non-vitural 的。
  2. 继承方式是 private

总结

  • 避免编译器暗自生成的拷贝功能,可以将相应的成员函数声明为 private 的。注意:在C++11新标准下,可以直接声明为 删除的。
  • 继承像 Uncopytable 的基类也是可行的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值