[关闭]
@lishuhuakai 2016-11-05T00:26:03.000000Z 字数 1777 阅读 1668

CPP常识 02 -- noncopyable

cpp


文章参考了这里http://blog.csdn.net/huang_xw/article/details/8248960

boost::noncopyable比较简单, 主要用于单例的情况.

通常情况下, 要写一个单例类就要在类的声明把它们的构造函数, 赋值函数, 析构函数, 复制构造函数隐藏到private或者protected之中, 每个类都这么做麻烦.

noncopyable类, 只要让单例类直接继承noncopyable.

class noncopyable的基本思想是把构造函数和析构函数设置protected权限,这样子类可以调用,但是外面的类不能调用,那么当子类需要定义构造函数的时候不至于通不过编译。但是最关键的是noncopyable把复制构造函数和复制赋值函数做成了private,这就意味着除非子类定义自己的copy构造和赋值函数,否则在子类没有定义的情况下,外面的调用者是不能够通过赋值和copy构造等手段来产生一个新的子类对象的

  1. #ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
  2. #define BOOST_NONCOPYABLE_HPP_INCLUDED
  3. namespace boost {
  4. // Private copy constructor and copy assignment ensure classes derived from
  5. // class noncopyable cannot be copied.
  6. // Contributed by Dave Abrahams
  7. namespace noncopyable_ // protection from unintended ADL
  8. {
  9. class noncopyable
  10. {
  11. protected:
  12. noncopyable() {}
  13. ~noncopyable() {}
  14. private: // emphasize the following members are private
  15. noncopyable( const noncopyable& );
  16. const noncopyable& operator=( const noncopyable& );
  17. };
  18. }
  19. typedef noncopyable_::noncopyable noncopyable;
  20. } // namespace boost
  21. #endif // BOOST_NONCOPYABLE_HPP_INCLUDED

给一个示例:

  1. #include "tfun.h"
  2. class myclass: public boost::noncopyable
  3. {
  4. public:
  5. myclass(){};
  6. myclass(int i){};
  7. };
  8. int main()
  9. {
  10. myclass cl1();
  11. myclass cl2(1);
  12. // myclass cl3(cl1); // error
  13. // myclass cl4(cl2); // error
  14. return 0;
  15. }

一个有意思的问题

根据cpp的继承规则,如果子类以private的形式继承父类的话:

我这里有一个问题:

  1. class A : boost::noncopyable
  2. {
  3. public:
  4. A () {}
  5. }
  6. class B : A
  7. {
  8. public:
  9. B() {}
  10. }

我的疑问是B类能够构造吗?我们来分析一下,A类以private的形式继承noncopyable,这意味着,noncopyable的构造函数和析构函数变成了A中的私有函数,是吧!

这样以来,B类构造的时候要调用A的构造函数,既然A的构造函数变成了private,那么B就不能构造了,不是吗?

推理似乎很漂亮,但是很遗憾,是错的,虽然很违反我们的直觉.

effective c++提到过这个问题的解释,我在这里摘抄一下:

在子类对象(derived class)对象的base class构造期间,该子类对象的类型是父类(base calss),而不是子类(derived class).在子类对象析构的时候这一条也成立.

至于为什么会有这么违反直觉的事情发生,可以查看effective c++的条款9:绝不在构造和析构过程中调用virtual函数.

结果显而易见,在B类调用A类的构造函数时,B类仍然是A类,所以可以访问noncopyable的构造函数.

好吧,cpp的坑可真多呢.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注