一、前言
在前面一篇文章中(https://blog.csdn.net/qq_41453285/article/details/104165762),我们介绍了C++编译器会为我们的class生成默认的构造函数、析构函数、拷贝构造函数、拷贝赋值运算符
但是有些情况下,
我们不希望使用其中的一种功能。例如:我们不希望使用class的拷贝赋值运算符(那么就不能将一个对象赋值给另一个对象),那么就需要使用一些手段来禁止使用这些功能
文本介绍一些方法来禁止编译器为我们提供的这些默认函数
二、方式①
如果我们不想使用某些函数,将这些不想使用的函数
在类中声明为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且没有定义
三、方式②
在前一篇文章的最后我们已经介绍过这一种情况,此处我们详细讲解(前一篇文章参阅:https://blog.csdn.net/qq_41453285/article/details/104165762)
方式①介绍的方法是不安全:因为如果在类的成员函数或friend函数中调用它们,即使是private的,也可以成功调用
方式②如下:
是在基类中将这些方法声明为private,然后继承于这个类,那么基类在使用这些函数时也不可以使用
在类的成员函数或friend函数中调用它们也会产生错误(因为基类的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的机制
作者:江南、董少
自动
c+
编译器
函数
C++
赋值