条款6:阻止编译器自动生成拷贝构造函数和赋值函数

来源:互联网 发布:wind python高频数据库 编辑:程序博客网 时间:2024/06/06 02:29
  • 为了阻止编译器默认生成拷贝构造函数和拷贝赋值函数,我们需要手动去重写这两个函数,某些情况下,为了避免调用拷贝构造函数和拷贝赋值函数,我们需要将他们设置成private,防止被调用。
  • 但是类的成员函数和friend函数还是可以调用private函数,如果这个private函数只申明不定义,则会产生一个连接错误;
  • 针对上述两种情况,我们可以定一个base类,在base类中将拷贝构造函数和拷贝赋值函数设置成private,那么派生类中编译器将不会自动生成这两个函数,且由于base类中该函数是私有的,因此,派生类将阻止编译器执行相关的操作。
  • 另一个例子,如果在base类中,我们把赋值构造函数定义为私有成员。派生类的赋值会怎么样呢?

    这时,如果我们没有定义赋值构造函数,则C++会拒绝为其派生类生成一个拷贝赋值操作符这些赋值操作。因为在赋值时,会让基类成员调用基类自己的赋值构造函数,但是这时是私有的,所以就会出问题。

class Uncopyable{protected:         Uncopyable(){}         ~Uncopyable(){}private:         Uncopyable(const Uncopyable&);         Uncopyable& operator= (const Uncopyable&);};class HomeForSale: public Uncopyable{…}; 

我们希望最后这两句话不能通过编译,那么怎样在C++中实现呢?一种想当然的做法,就是不去写拷贝构造函数和赋值运算符。但由上一个条款可以知道,这样做是行不通的,C++编译器会我们生成四个默认的成员函数,其中就有拷贝构造函数和赋值运算符,所以不写是不能解决问题的。如果写了呢?这确实是一个突破口,自己写了成员函数,编译器就不会生成默认的了,但不能写在public里,因为public的函数都是可以在外部被调用的,一种好的方法就将这些函数写在private或者protected里面,大概像这样:

class HomeForSale{ private:          HomeForSale(const HomeForSale& house){...}          HomeForSale& operator= (const HomeForSale& house){...} };
好了,这样做编译器就不会为我们生成默认的了,同时因为是在private访问权限下定义的,所以也不会担心在外部被调用了,下面这两句话是无法通过编译的:
HomeForSale house3(house1); // 无法通过编译house2 = house1; // 无法通过编译

但还要考虑到一种特殊的情况,就是万一在类中出现了友元函数或者友元类,它们可以访问到private下的成员函数,这很危险,怎样才能避免这种情况?

其实只要小改一下就行了,把定义换成声明,这样子:

class HomeForSale{ private:          HomeForSale(const HomeForSale&);          HomeForSale& operator= (const HomeForSale&);};

这样即使通过编译,链接器也会报错的,因为只有声明而没有具体的实现。那现在回过头来问一下,能不能不要搞特殊,直接把拷贝构造函数和赋值运算符声明在public下,只是不要实现之?

这种方法是可以的,因为链接器不会放过这个只有声明的空架子,但这不是一种好的解决方法。因为有这样一个编程的原则:错误越早被发现就越好。编译要早于链接,所以在编译发现错误要优于在链接阶段才发现的错误,可以节省时间,提高效率。

下面是书上提到的一个应用:

class Uncopyable{ protected:          Uncopyable(){}          ~Uncopyable(){} private:          Uncopyable(const Uncopyable&);          Uncopyable& operator= (const Uncopyable&);};class HomeForSale: private Uncopyable{…};

这样HomeForSale就不能被拷贝了。这里的继承可以不是public,比如private。

一句话总结一下:为了驳回编译器自动提供的机能(比如可拷贝),可将相应的成员函数声明为private且不予实现。还有一种方法,继承Uncopyable也行






阅读全文
0 0