如何禁止对象之间的拷贝?
将构造函数和析构函数中的任意一个设置为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,而子类不去覆盖该方法就行了。友元函数也无法破坏这种设计,因为基类的友元函数无法破坏基类的封装性。友元函数和类是一对一的关系,无法破坏基类或者父类的封装性。