条款10 若不想使用编译器自动生成的函数,就该明确拒绝
如果一个对象,只是希望他可以被创造出来,不希望被拷贝,那么最先想到的应该是将拷贝和复制运算符私有化:
class A { public: A(){} ~A(){} private: A(const A&){} A& operator=(const A&) {} };
但是书中大师认为,有两类函数仍然可以访问:成员函数和友元函数,如下:
#include<iostream> using namespace std; class A { public: A(){} ~A(){} friend void MyCopyA_One(); void MyCopyA_Two() { A a; A b(a); b = a; } private: A(const A&){} A& operator=(const A&) {} }; void MyCopyA_One() { A a; A b(a); b = a; } int main() { MyCopyA_One(); A a; a.MyCopyA_Two(); while (1); return 0; }
解决方法是对于私有的拷贝构造函数和赋值运算不定义,那么链接的时候就会因为找不到拷贝或者赋值运算的定义而链接失败,如下:
但是这个错误是在链接的时候才会有的,能不能把错误提前到编译时期,于是大师为我们提供了如下方案:
#include<iostream> using namespace std; class Uncopyable { public: Uncopyable(){} ~Uncopyable(){} private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); }; class A :private Uncopyable { public: }; int main() { A a; //A b(a); 编译不过 //b = a; 编译不过 while (1); return 0; }
解释:因为子类在调用构造函数时先会调用父类的构造函数,这里由于父类没有定义,所以会编译不过。