Item 6:禁用那些不需要的缺省方法
拒绝编译器自动提供的机制
将拷贝构造函数和拷贝赋值运算符声明为私有的。通过显式声明一个成员函数,可以防止编译器生成它自己的版本,而且将这个函数声明为私有的,可以防止别人调用它。
通常,这个方案并不十分保险,因为成员和友元函数还是能够调用你的 private 函数。换句话说,除非你十分聪明地不定义它们。那么,当有人不小心地调用了它们,在 link-time(链接时)会出现错误。这个窍门——声明成员函数为 private 却故意不去实现它确实很好。
class HomeForSale {
public:
...
private:
...
//@ declarations only
HomeForSale(const HomeForSale&);
HomeForSale& operator=(const HomeForSale&);
};
对于上面的类定义,编译器将阻止客户拷贝对象的企图,如果你不小心在成员或友元函数中这样做了,连接程序会提出抗议。
通常的方式故意设计一个基类:
class Uncopyable {
protected:
Uncopyable() {}
~Uncopyable() {}
private:
//@but prevent copying
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
此时 HomeForSale 可以从该基类继承:
class HomeForSale: private Uncopyable {
...
};
这样做是因为,如果有人—— 成员友元函数试图拷贝一个 HomeForSale 对象,编译器将试图生成一个拷贝构造函数和一个拷贝赋值运算符。这些函数的编译器生成版会试图调用基类的相应函数,而这些调用将被拒绝,因为在 基类中,拷贝操作是私有的。
Uncopyable 的实现和使用包含一些微妙之处,比如,从 Uncopyable 继承不必是 public的,而且 Uncopyable 的 析构函数不必是 virtual 的。因为 Uncopyable 不包含数据。
总结
- 为了拒绝编译器自动提供的机能,将相应的成员函数声明为 private,而且不要给出实现。使用一个类似 Uncopyable 的基类是方法之一。