如何禁止对象之间的拷贝?
将构造函数和析构函数中的任意一个设置为private,如下:
class A{ public: A(){}; private: ~A(){}; A(const A&a){}; A &operator=(const A&a){return a;} };
A a;
编译报错提示:Variable of type 'A' has private destructor.
我们知道,如果我们不显性的声明拷贝构造函数和重载=,那么编译器会为我们提供默认的拷贝构造函数和copy assignment函数。这样一来,对象间的拷贝就会发生,如果要禁止对象间的拷贝,那么就要显性的声明,无需定义。
class A{ public: A(){}; ~A(){}; A(const A&a){}; private: A &operator=(const A&a){return a;} }; A c,d; c=d;
编译报错:'operator=' is a private member of 'A'
但是我们如果把友元函数写进class A,那就破坏了其封装性,也就破坏了我们禁止拷贝的意图。请看如下代码:
class A{ public: A(int i){_b=i;}; ~A(){}; A(A&a){}; void printA() const { cout<<_b<<endl; } friend void copy(A &a, A &b); private: A &operator=(A&a){return a;} int _b; }; void copy(A &a, A &b) { b._b=a._b; } int main(int argc, const char * argv[]) { A c(1); A d(2); copy(c,d); d.printA(); return 0; }
运行结构是1,证明对象间拷贝成功。那么有什么简单的方法禁止拷贝,而且又很优雅呢?定义一个基类class noncopyable,让A去继承noncopyable,这样就A生成的对象不能拷贝了。
class noncopyable{ public: noncopyable(){} ~noncopyable(){} private: noncopyable(const noncopyable&); const noncopyable &operator=(const noncopyable &); }; class A : public noncopyable { ... }; A c(1); A d(2); d=c;
编译报错:Object of type 'A' cannot be assigned because its copy assignment operator is implicitly deleted。此时,由于继承了noncopyable类,而noncopyable的运算符重载声明为private,故导致其子类拷贝失败。这是一种思路,若有些行为不想发生,可定义一个基类,声明该方法为private,而子类不去覆盖该方法就行了。友元函数也无法破坏这种设计,因为基类的友元函数无法破坏基类的封装性。友元函数和类是一对一的关系,无法破坏基类或者父类的封装性。