一、前言
二、方式①
- 如果我们不想使用某些函数,将这些不想使用的函数在类中声明为private,那么就不能使用这些函数了
- 注意事项:
- 如果声明为private的话,那么就只需要声明就行了,不需要定义,因为我们程序是不会使用到这些函数的
- 如果将拷贝构造函数声明为private从而不想使用它,那么我们就必须显式给出构造函数。原因:如果不给出构造函数,那么在定义对象时,对象会将以为拷贝构造函数为构造函数而调用它,但是它是private,从而不允许定义对象
- 演示案例如下:
class A
{
public:
A() {} //必须显式定义构造函数,如果不定义那么就不能定义对象
private:
//只需要声明即可,因为我们不会使用到这两个函数了(并且也不需要给出参数)
A(const A&);
A& operator=(const A&);
};
A a; //正确(如果不定义构造函数,那么a会以拷贝构造函数进行初始化)
A a2(a); //错误(拷贝构造函数为private)
a2=a; //错误(拷贝赋值函数为private)
“只声明而不定义”的不安全性
- 上面我们说过如果将其声明为private之后,那么可以之声明而不定义它们
- 但是这个方法不是绝对安全的:
- 因为如果类的成员函数或friend函数中调用它们,即使是private的,也可以成功调用
- 又假设如果我们希望类的成员函数或friend函数调用它们,但在调用时会发现只有声明而无定义,因此链接时会错误
- 在C++ iostream程序中的应用:这种手法被用在C++ iostream程序库中阻止拷贝行为。如果查看ios_base,basic_ios和sentry的源码会发现,它们的拷贝构造函数和拷贝赋值运算符都被声明为private且没有定义
三、方式②
演示案例
- 我们专门为了阻止拷贝动作设计了一个Uncopyable基类,然后将自己的类继承于这个类
class Uncopyable
{
public:
Uncopyable() {}
~Uncopyable() {}
private:
//声明为private
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
class A :public Uncopyable
{
//...
};
- 这种方法的好处:
- ①无论以何种方式(public、protected、private)继承于Uncopyable都可以
- ②Uncopyable的析构函数不一定得定义为virtual
- ③Unable不含数据,符合条款19所描述的“empty base class optimization”
四、Boost库的noncopyable类
- Boost库的noncopyable类与上面“三”中介绍的Uncopyable类类似。详情可以自行查阅
五、总结
- 为了不使用编译器自动提供的功能,可将相应的成员函数声明为private并且不予实现。使用像上面介绍的Uncopyable的机制