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

总结如下:

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值