【复读EffectiveC++06】条款06:若不想使用编译器自动生成的函数,就该明确拒绝

本文介绍了如何在C++中通过将拷贝构造函数设为私有、继承Uncopyable类以及使用C++11的`=delete`来拒绝编译器自动生成的拷贝构造函数,以实现单例模式或其他特定需求。
摘要由CSDN通过智能技术生成

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

关于条款05提到的内容,条款06就是在展开有关 “ 拒绝自动生成 ” 的事情。
其描绘一种场景,此场景被要求一个类的实例化对象只有一份,近似于单例模式,在这种情况下拷贝构造函数是不需要的,进而考虑如何去拒绝编译器的自动生成,原书给了三种解决方法:
a、将显式声明为private,函数定义为空
b、使用继承的方式
c、使用= delete

一、将显式声明为private,函数定义为空

编译器默认生成的成员函数,具有一个重要前提,成员函数属性为:公有(public) 。
针对此特性,可以将成员函数的属性改为私有(private) 。

class HomeForsale{
public:
    ...
private:
    ...
    HomeForsale(const Home For sale&);
    HomeForsale& operator=(const HomeForSale&);
}

该方法简单易懂,是绝大部分应用场景的通解,但要注意不能对此进行定义,否则同类成员函数和友元函数(friend)依然可以调用它们。
此外,多一句嘴,C++ iostream库就是用了这一策略。

二、使用继承的方式

class Uncopyable{
protected:
    Uncopyable(){}
    ~Uncopyableo(){}
private:
    Uncopyable(const Uncopyable&);
    Uncopyable& operator=(const Uncopyable&);
}

class HomeForsale:private Uncopyable{...};

我们都只道,派生类使用到构造函数的时候会优先调用基类的构造函数,而拷贝构造函数也是同样的会被先于子类的。
利用以上的特性,可以想到,当基类的拷贝构造函数被声明为private时,派生类调用基类的拷贝构造函数失败,因此派生类的对象赋值失败,以此达到拒绝的目的。
此方法虽然需要继承,看上去会稍显复杂,但这种方法可以将连接期的错误转移至编译期,而且当成员函数和友元函数调用它们时,会出现编译错误。
最后,如果有此类需求,可以去boost库看看,有一个noncopyable类,继承它就可以了。

三、使用= delete

class cMyObj
{
public:
	cMyObj(){}
	~cMyObj(){}
private:
	cMyObj(const cMyObj& obj) = delete//直接禁用
	cMyObj& operator=(const cMyObj& obj) = delete}

除以上两种原书的方法,甚至还可以使用 C++11 引入的 =delete,这是一种 “ 新 ” 特性,它用于明确禁用或删除类的成员函数、特殊成员函数、或者其他成员函数。

此特性的主要目的是在编译时捕获潜在的错误,并提供更精确的控制,以确保类的行为符合设计要求

同样的此特性也存在着使用范围:
a、只能用于成员函数或全局函数:=delete 只能用于类的成员函数、全局函数或者重载操作符,不能用于局部变量、局部函数或类的数据成员。
b、不能用于默认函数参数: 不能在函数的默认参数上使用 =delete。
c、不能用于虚函数: 不能使用 =delete 来删除虚函数,虚函数应该使用纯虚函数(virtual void func() = 0;)来声明。
d、不能用于非特殊成员函数的重载:=delete 不能用于非特殊成员函数的重载,例如,你不能使用 =delete 来删除一个普通成员函数,只能用于特殊成员函数,如构造函数、复制构造函数等。
e、类型相关性:删除的函数必须与实际调用匹配,否则编译器可能会产生不一致的行为。
f、友元函数:友元函数通常不受 =delete 影响,因为它们不属于类的成员函数。

四、总结

为驳回编译器自动(暗自)提供的机能,可将相应的成员函数声明为private并且不予实现。使用想Uncopyable这样的base class 也是一种做法。

视情况去选用,有时候,同事能不能理解也是一种情况,不然后果你懂的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值