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 的基类是方法之一。
posted @ 2020-01-02 09:42  刘-皇叔  阅读(121)  评论(0编辑  收藏  举报