条款06:若不想编译器自动生成的函数,就该明确拒绝

来源:互联网 发布:u盘照片如何导入mac 编辑:程序博客网 时间:2024/06/04 18:20

总结如下:

1.想要防止对象的拷贝,你可以将拷贝构造函数和赋值运算符重载函数声明为private,而且不实现他们,这样在对象试图拷贝的时候就会报出链接错误。

class A{public:A(int x) :_a(x){}private:int _a;A(const A&);//声明私有拷贝构造函数A& operator=(const A&);//声明私有赋值运算符重载};
在上面的函数声明中,没有写出来参数的名称,在这里参数的名称并不重要,因为这个函数并没有被实现,指定参数名称也没什么用,当然写上名称也没错

2.其实可以将防拷贝中在链接期间发生的错误提前至编译期间,毕竟越早检查出来错误越好。

   实现方式:将拷贝构造函数和赋值运算符重载函数单独封装在一个base类中

class A{public:A();~A();private:A(const A& s);//声明私有拷贝构造函数A& operator=(const A& s);//声明私有赋值运算符重载};
上面是单纯的封装了拷贝构造函数和赋值运算符重载的函数的类

加入我现在不想让B类被拷贝,只需要继承A类就可以了,

private:A(const A& s);//声明私有拷贝构造函数A& operator=(const A& s);//声明私有赋值运算符重载};class B :public A{private:int _a;public:B(int a) :_a(a){}};
这样B类对象就可以防止被拷贝了,同时将报错提前在了编译期间,因为B类没有声明拷贝构造函数和赋值运算符重载函数,只要任何东西想拷贝其B类的对象,编译器会尝试生成一个拷贝构造函数和赋值运算符重载函数u,生成的函数会调用其基类的base相对应的函数,而这个行为会被编译器拒绝,因为基类的这些函数是private的,不可被外界访问。

但是这种用法也有一定的缺陷,比如B类还有可能继承其他的类,这就会导致多继承,从而阻止空基类最优化(EBO或者EBCO)!所以在下面我来解释一下什么是基类最优化

class Empty{};
首先来看中这个空类的大小,用sizeof(Empty)为1(在Linux下测试也为1),为什么不是0而是1呢,因为C++编译器规定每个实体对象都要有不同的地址,编译器会给默默给这个空类插入一个字节,这样实例话的对象就会有不同的地址,其实这里的1个字节是用来占位的,后面开辟的对象就可以在不同的地址上了。

(附加,C语言中空结构体的大小为0,但是我在vs上测试不允许定义这么一个空的结构体,而在Linux下其大小为0,这个主要取决于编译器)

空类最优化就是当一个空类被派生类继承的时候,编译器会优化掉空类所占的一个字节。这就是空类最优化,注意只能是单继承中才会进行最优化。

class Empty{};class Dervice:public Empty{int _x;};int main(){Dervice s;cout << sizeof(s) << endl;system("pause");return 0;}
这个代码的输出就4(进行了空类最优化)

比如下面这些就没有最优化

class Empty{};class Dervice{Empty a;int _x;};int main(){Dervice s;cout << sizeof(s) << endl;system("pause");return 0;}

因为空类大小为1,根据结构体对其原则(如果不直到的话我C语言部分的博客有讲)得出大小为8。

阅读全文
0 0
原创粉丝点击