当我们定义一个类时,我们显示地或隐式地指定在此类型的对象拷贝、移动、赋值和销毁时做什么。一个类通过定义五种特殊的成员函数来控制这些操作,包括:拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符和析构函数。我们称这些操作作为拷贝控制操作。
如果一个类没有定义所有的这些拷贝控制成员,编译器会自动为它定义缺失的操作。很多类会忽略这些拷贝控制操作。但是,对一些类来说,依赖这些操作的默认设定会导致灾难。
有时候,当我们定义某个类时,我们可能不希望我们定义的类进行拷贝操作。为此,我们可以采用将拷贝构造和拷贝赋值声明为PRivate(私有)的,这样的话就能禁止类进行拷贝操作。不过,这样做的话,显得比较麻烦。为此,boost中就提供noncopyable,我们通过继承noncopyable就可以实现禁止拷贝了。
下面是boost::noncopyable类的实现。在实现中,将构造函数和析构函数声明为保护,这样不会影响noncopyable作为基类,也避免外部构建一个noncopyable实类。
namespace noncopyable_ // protection from unintended ADL{ class noncopyable { protected: noncopyable() {} ~noncopyable() {} private: // emphasize the following members are private noncopyable( const noncopyable& ); noncopyable& Operator=( const noncopyable& ); }; typedef noncopyable_::noncopyable noncopyable;};那么,问题来了。为什么将noncopyable作为基类,能使派生类实现禁止拷贝? 这是因为,在派生类拷贝过程中,主要分为2部分:首先,调用基类的复制构造函数完成基类部分的复制,然后再复制派生类的部分。由于基类的拷贝构造函数和拷贝赋值运算符声明为私有的,派生类无法访问。所以,在第一部分的时候已经失败了,这就成功的禁止派生类的拷贝功能。
我们可以尝试写如下的测试代码,编译环境VS2013。
当我们未使用boost::noncopyable时:
class MyClass {public: MyClass() {} ~MyClass() {}};int main(void){ MyClass CMySrc; MyClass CMyDest; MyClass CMyDest1(CMySrc); CMyDest = CMySrc; return 0;}此时,编译成功。
当我们使用boost::noncopyable时:
#include <boost/noncopyable.hpp>class MyClass : public boost::noncopyable{public: MyClass() {} ~MyClass() {}};int main(void){ MyClass CMySrc; MyClass CMyDest; MyClass CMyDest1(CMySrc); //错误 CMyDest = CMySrc; //错误 return 0;}此时,编译不通过。说明确实禁止了类的拷贝功能。
新闻热点
疑难解答