Effective C++条款06:构造/析构/赋值运算之(若不想使用编译器自动生成的函数,就该明确拒绝)

一、前言

  • 在前面一篇文章中(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的机制
发布了1399 篇原创文章 · 获赞 958 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/qq_41453285/article/details/104166471