1.问题引入
试想如下情形,某个房地产商所拥有的房子都是不同的。同时,你在为这个公司设计程序,而你不想将一座房子的信息拷贝给另一座房子,这就需要禁止使用拷贝构造函数和拷贝赋值运算符(copy assignment operator)。如下例所示:
1#include <iostream> 2 3class House 4{ 5 // ... 6}; 7 8int main() 9{ 10 House h1; 11 House h2; 12 House h3(h1); // 禁止执行默认的拷贝构造函数 13 h1 = h2; // 禁止执行默认的拷贝赋值运算符 14 15 return 0; 16}
如果是其他功能,不想使用的话不声明即可。但是对于以上这两个功能,像昨天的文章C++类中默认生成的函数所说的。即使你不声明不定义,编译器还是会为该类自动生成的。
2.解决方法
解决方法:首先,因为编译器为类自动生成的函数都是共有(public)的,所以我们就可以把这些函数声明为私有(private),这样类生成的对象就无权限调用它们。其次,只声明不定义。因为如果有定义,本类和友元函数(friend functions)还是可以调用它们。如下例所示:
1#include <iostream> 2 3class House 4{ 5public: 6 // ... 7private: 8 House (const House&); // 只声明,不定义拷贝构造函数。同时要设为private!由于根本就不会用到它们,所以可以不必写形参了 9 House& operator=(const House&); // 只声明,不定义拷贝赋值运算符。同时要设为private!由于根本就不会用到它们,所以可以不必写形参了 10};
因此,当你在代码中试图拷贝对象,编译器就会报错。然而,如果你不小心在该类的成员函数或者友元函数中调用了private权限自动生成的函数,由于找不到自动生成函数的定义,链接器则会出错。但是,将所有报错提前到编译器不是更好吗?这样就可以越早的检测出错误了。
3.更好的解决方法
昨天的文章C++类中默认生成的函数中也提到了,当一个父类将拷贝构造函数和拷贝赋值运算符声明为私有时,编译器会拒绝为它的子类生成拷贝构造函数和拷贝赋值运算符。因此我们可以专门使用一个父类,在父类当中声明拷贝操作为私有(private),并让我们的类继承自它。这样,当成员函数或友元函数试图拷贝House对象时,所有关于拷贝的操作都会提前在编译阶段报错。如下例所示:
1#include <iostream> 2 3class Uncopyable{ 4protected: 5 Uncopyable(){} 6 ~Uncopyable(){} 7private: 8 Uncopyable(const Uncopyable&); 9 Uncopyable& operator=(const Uncopyable&); 10}; 11 12class House: public Uncopyable{ 13// ... 14};
4.总结
(1).当不想让编译器为类自动生成某些函数时,把这些不想要的函数声明在此类的私有成员中并不予以定义。或者,更好的方法使用像上例中定义一个Uncopyable父类,并让我们的House类公有继承自它。