zoukankan      html  css  js  c++  java
  • [Effective C++ --006]若不能使用编译器自动生成的函数,就该明确拒绝

    ■本文内容■
    □第一节 <引言>
    在条款五的讲解中,我们已经知道编译器是聪明的家伙,它会帮助你生成类的构造函数、析构函数、一个copy构造函数和一个赋值运算符。
    有时真的要感谢编译器所做的这一切,因为我们确实需要如此。但有的时候这一切又会给我们带来麻烦,本条款的介绍主题是麻烦的产生及如何解决。

    □第二节 <案例:人员管理系统>
    在一个人员管理系统中,有个class来描述每个人的信息是再合理不过的。
    class PersonInfo{...};
    那么下面的声明是合理的。
    PersonInfo hanHan;
    PersonInfo fangZhouZi;
    那么下面的赋值也是合理的。
    Person biaoGe(hanHan); // 用韩寒的信息拷贝出表哥--合理吗
    hanHan = fangZhouZi; // 让韩寒成为方舟子--合理吗
    显然,在现实中这些都是不合理的:要不违反伦理(克隆),要不目前的科技尚不能实现。对于编译器来说这没有什么不妥的地方。
    所以我们要做的就是要让这逆天的情况永远不要发生。

    □第三节 <寻找真凶>
    好吧,也许写PersonInfo类的程序猿的本意并不是如此,但事实发生了就要找到真凶。其实,真凶也不难找到,就是那个自作聪明的编译器。
    因为程序猿并没有声明Copy构造函数和Copy操作符。因为条款五中已经指出,如果你声明它们,而某些人尝试调用它们,编译器就会声明。

    □第四节 <阻止犯罪>
    如果在现实中,犯这么严重的罪,编译器肯定被抓去劳动改造了。既然不能给编译器判刑,那就要想个办法,防止它继续犯罪。
    程序猿经过三天两夜的苦思冥想终于想到了一个自认为很好的方法。因为由编译器产生的函数都是public的,所以只要我自行定义它们,并且
    以private修饰,那么编译器就不会生成它们了。但后来这个方法并不是绝对安全,因为成员函数和友元函数还是可以调用private函数的。
    程序猿灵机一动:可以不实现这些函数啊。于是就有了下面的代码。

    class PersonInfo {
    public:
    ...
    private:
    PersonInfo(const PersonInfo&);
    PersonInfo& operator=(const PersonInfo&);
    };


    再来看一下代码。private修饰符限定了只有成员函数和友元函数调用Copy函数和赋值运算符;而当真正调用的时候,由于未定义,连接器会报错。

    程序猿是个好学生,他觉得错误可以在编译的阶段就被发现。事实上还真的被他找到了。于是他又写出了下面的代码。

    class UnCopyable {
    protected:
        UnCopyable() {}
        ~UnCopyable() {}
    private:
        UnCopyable(const UnCopyable&);
        UnCopyable& operator=(const UnCopyable&);
    };
    class PersonInfo : private UnCopyable {
        ...
    };

    再来看一下代码。只要任何人拷贝PersonInfo对象,编译器就会试着生成一个Copy构造函数和一个Copy操作符。
    在尝试调用UnCopyable的对应的兄弟,很显然会被编译器毫不留情的拒绝:因为它们是private类型的。

    到此,事情有了完美的结局,程序猿完美的避免了逆天的事再发生,编译器还是像以前一样尽职尽责。

    ■总结■
    如果不需要编译器献的殷勤,就明确的拒绝它。拒绝的方式是可将相应的成员函数声明为private,并且不予实现。
    或者像UnCopyable这样类也是一种做法,虽然会产生多重继承的问题。
    目前该条准则在GUI项目中并没有发现有使用的地方。
    (注:文中所用的人名、称呼等均不带有任何感情色彩,请勿对号入座!)

  • 相关阅读:
    关于Spring的69个面试问答——终极列表
    阿里内部分享:我们是如何?深度定制高性能MySQL的
    转载:SqlServer数据库性能优化详解
    SQL Server 中WITH (NOLOCK)浅析
    使用druid连接池带来的坑testOnBorrow=false
    opencms9.0安装
    POJ 1201-Intervals(差分约束系统)
    SQL Server 为代码减负之存储过程
    XMPP系列(四)---发送和接收文字消息,获取历史消息功能
    【POJ 2482】 Stars in Your Window(线段树+离散化+扫描线)
  • 原文地址:https://www.cnblogs.com/hustcser/p/4087610.html
Copyright © 2011-2022 走看看