「Effective C++」条款06: 若不想使用编译器自动生成的函数,就该明确拒绝

一·编译器自动生成了哪些成员函数?

成员函数作用
构造函数初始化对象成员(不是开辟空间,开辟空间是new)
析构函数编译器销毁对象,然后自动调用析构函数清理资源
拷贝构造函数已存在的对象初始化新对对象时调用
运算符重载已存在对象赋值已存在对象时调用
取地址重载不常重载
const取地址重载不常重载

关于编译器自动生成的函数的更加详细的介绍,请参考:
「Effective C++」条款05: 了解c++默默编写并调用了哪些函数

二·为什么会不想使用编译器自动生成的函数?

经典的例子就是设计模式的单例模式【Singleton】,在单例模式中,我们要求对象只有一份,所以必须拒绝被一些编译器生成的函数来防止对象被拷贝(对象被拷贝使用的是拷贝构造函数的赋值运算符重载,所以应当拒绝这两个函数,但是在实际的工作中需要拒绝哪些函数应该根据实际情况来判断)。

·简单单例模式代码举例:

class Singleton
{
public:
	Singleton(const Singleton& obj) = delete;
	Singleton& operator=(const Singleton& obj) = delete;
	
	static Singleton* getInstance()
	{
		return m_obj;
	}
private:
	Singleton() = default;
	~Singleton() = default;
	static Singleton* m_obj;
};
Singleton* Singleton::m_obj=new Singleton;

int main()
{
	Singleton* obj=Singleton::getinstance();
}

在这个例子中,我们要求m_obj始终只有一份拷贝,所以需要拒绝拷贝构造函数和运算符重载,防止对象被拷贝。

三·编译器生成的成员函数的特性

  1. 编译器默认生成的成员函数的属性为:public
  2. 用户写了相应的成员函数,编译器则不再自动生成
  3. 编译器默认生成的函数都可以调用

四·几种拒绝的方式和优缺点

·方式一:将拷贝构造函数和赋值运算符重载显式声明为private,函数定义为空

优点:操作简单,能够应付大多数场景

缺点:友元依旧可以操作定义为private的成员函数,或者使用公共成员函数也可以调用声明为private的成员函数

代码举例:

class Student
{
public:
	Student(){}
	~Student(){}
private:
	Student(const Singleton& obj){}       //声明为private,并定义为空来防止拒绝使用这两个函数
	Student& operator=(const Singleton& obj){}
}
·方式二:使用= delete

优点:操作更简单,更加直观的表示要禁用这个函数

示例代码:

class Student
{
public:
	Student(){}
	~Student(){}
private:
	Student(const Singleton& obj) = delete;     //直接禁用
	Student& operator=(const Singleton& obj) = delete;
}
·方式三:使用继承的方式

优点:比较精妙(…)

缺点:需要继承,操作相比其他方式稍显复杂

//首先设计基类
class People
{
public:
	People(){}
	~People(){}
private:
	People(const Singleton& obj);     //一定要设置为private
	People& operator=(const Singleton& obj);
}


//设计子类,继承于People类
class Student : public People
{
public:
	Student(){}
	~Student(){}
}


int main()
{
	Student Tom;
	Student Jack;
	Jack = Tom;       //编译器报错,原因:我们都只道,子类使用到构造函数的时候会优先调用父类的构造函数,而拷贝构造函数也是同样的会被先于子类的
					//构造函数调用,但是父类的拷贝构造函数被声明为private,所以调用失败,所以子类的对象赋值失败,达到拒绝的目的。
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值