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

Effective C++——条款06:若不想用编译器自动生成的构早函数,就应该明确的拒绝,第1张

Explicitly disallow the use of compiler-generated functions you do not want.

笔者注:本书早在C++11之前就被写出,所以作者在这里的所有方法,全部为C++11之前的做法。


在C++11之后,我们可以使用更加简洁的语法,更加可读的代码来完成同样的 *** 作。


 

如题目,为了避免一些不必要的麻烦 若不想用编译器自动生成的构早函数,就应该明确的拒绝,这样的做法很有意义。


世界上没有任何一片雪花是一样的,那我们就不能复制一个雪花对象,换句话说,我们不希望学花类又拷贝构造函数和拷贝赋值运算符。


在C++11之前

我们可以将方法声明为private,并且不予任何的实现,这样对于类的外部来说,是完全不可用的。


我们就能达到类似删除这个方法的 *** 作(编译器通常会提供一些默认的方法),比如这样。


class Snowflake
{
private:
    string shape;
    Snowflake(const Snowflake &);
    Snowflake& operator=(const Snowflake&);
public:
    Snowflake(const string & _shape) : shape(_shape) { }
};

当我们这样调用的时候

int main()
{
    Snowflake sf1("big");
    Snowflake sf2 = sf1;
    return 0;
}

会给出XXX函数不可方访问的编译器错误。


将链接期或者运行期的错误移动至编译器的当然是好事,毕竟越早的侦测出错误越好。


这样写出来的类还不能对付友元函数或者是其他成员调用——我们是想彻底的 ”删除“ 这个方法,不希望它被任何形式的调用。


这样还是会导致一些链接期间的错误。


我们有一个更好的实现方法。


就是专门封装一个基被类用于继承——控制子类中的方法可调用情况。


也就是这样。


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

class Snowflake : private Uncopyuable
{
private:
    string shape;
public:
    Snowflake(const string & _shape) : shape(_shape) { }
};

因为在编译器在为子类生成方式时会调用器对应父类的方法——父类中的方法被声明为了private,这样无论是友元还是成员函数调用,都会获得一个编译期间的错误——非常的人性。


关于书中其他的一些细节,还是不提了,C++11已经给了我们一个足够好的解决办法——那么我们问什么不使用呢?

C++11的方法

很简单,如果我们想删除某一个方法,我们可以明确的指定其是被删除的(当然是不能定义的了,上一种方法你可以定义,单使用C++11语法就真的delete了)。


class Snowflake
{
    Snowflake(const Snowflake &) = delete;
    Snowflake& operator=(const Snowflake&) = delete;
private:
    string shape;
public:
    Snowflake(const string & _shape) : shape(_shape) { }
};

还是十分的方便。


请记住

为驳回编译器自动(暗自)提供的功能,儿科将相应的成员函数声明为private并且不予实现。


使用像Uncopyabel这样的base class也是一种做法。


笔者加:

C++中使用delete关键字课很好的解决这类问题 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/565168.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-06
下一篇 2022-04-06

发表评论

登录后才能评论

评论列表(0条)

保存