Item 6: Explicitly disallow the use of compiler-generated functions you do not want
其实这一节的内容是和item5紧密相连的,上一节的核心围绕着编译器会自动生成类的一些方法,那么这一节就是围绕着如何去避免这些自动生成的方法。
前一节说到如果想要编译器避免自动生成,解决方法就是自己来写一个,而且要保证写的这个“用不了”,所以办法就是声明为private修饰的。
但是这样做其实是不够安全的,原因就是成员函数是可以调用private的方法,再就是友元函数也可以调用。除非你足够聪明保证不去定义这些。
解决办法就是把这些函数声明成private,并且故意不去实现它们。书上说到这种做法很常见,在标准库中I/O为了避免拷贝行为都是这样做的。这时如果是在成员函数或者友元中调用了这些方法,虽然编译是没有问题,但是会在链接阶段发生错误,因为这个private函数啥都没做。
书上接着说到一种更好的办法来实现能把这个链接阶段的错误提前到编译期,具体做法是:
设计一个专门组织拷贝的类,在这个类中把它的拷贝构造函数和拷贝赋值运算符声明为private
class Uncopyable {
protected: // allow construction and destruction of derived objects...
Uncopyable() {}
~Uncopyable() {}
private:
Uncopyable(const Uncopyable&); // ...but prevent copying
Uncopyable& operator=(const Uncopyable&);
};
这个类是由于构造函数和析构函数是protected,所以它的派生类是可以调用。但是拷贝构造函数和拷贝赋值运算符都是private
接着把需要控制的类继承到这个Uncopyable类
class HomeForSale: private Uncopyable { // class no longer declares copy ctor or copy assign operator
...
};
此时,如果有任何情况(包括成员函数和友元函数)尝试去拷贝这个HomeForSale对象的话,编译器会尝试生成HomeForSale的拷贝构造函数和拷贝赋值运算符,但是因为派生类进行拷贝的时候会把基类的内容也要拷贝(item12会讲到),所以会调用Uncopyable的拷贝构造函数或者拷贝赋值运算符,但是由于是private,所以会被编译器发现错误。
书上还说到这个Uncopyable类的设计很精妙,提到了很多点都是在书的后面内容讲到,在后面学习到再进行补充。
总结一下这一节的点:
为了避免编译器自动生成的某些函数,通常有两种方法: