zoukankan      html  css  js  c++  java
  • 读书笔记_Effective_C++_条款六:若不想使用编译器自动生成的函数,就该明确拒绝

    举个书上的例子,地产中介商卖的是房子,有这样一个类:

    class HomeForSale
    {…}

    每个房子都是不一样的,所以希望这样:

    1 HomeForSale house1;
    2 HomeForSale house2;
    3 HomeForSale house3(house1); // house3企图与house1相同,不能通过这种情况
    4 house2 = house1; // house2也不应该与house1相同,也不能通过这种情况

    我们希望最后这两句话不能通过编译,那么怎样在C++中实现呢?一种想当然的做法,就是不去写拷贝构造函数和赋值运算符。但由上一个条款可以知道,这样做是行不通的,C++编译器会我们生成四个默认的成员函数,其中就有拷贝构造函数和赋值运算符,所以不写是不能解决问题的。如果写了呢?这确实是一个突破口,自己写了成员函数,编译器就不会生成默认的了,但不能写在public里,因为public的函数都是可以在外部被调用的,一种好的方法就将这些函数写在private或者protected里面,大概像这样:

    1 class HomeForSale
    2 {
    3 private:
    4          HomeForSale(const HomeForSale& house){...}
    5          HomeForSale& operator= (const HomeForSale& house){...}
    6 };

    好了,这样做编译器就不会为我们生成默认的了,同时因为是在private访问权限下定义的,所以也不会担心在外部被调用了,下面这两句话是无法通过编译的:

    1 HomeForSale house3(house1); // 无法通过编译
    2 house2 = house1; // 无法通过编译

    但还要考虑到一种特殊的情况,就是万一在类中出现了友元函数或者友元类,它们可以访问到private下的成员函数,这很危险,怎样才能避免这种情况?

    其实只要小改一下就行了,把定义换成声明,这样子:

    1 class HomeForSale
    2 {
    3 private:
    4          HomeForSale(const HomeForSale&);
    5          HomeForSale& operator= (const HomeForSale&);
    6 };

    这样即使通过编译,链接器也会报错的,因为只有声明而没有具体的实现。那现在回过头来问一下,能不能不要搞特殊,直接把拷贝构造函数和赋值运算符声明在public下,只是不要实现之?

    这种方法是可以的,因为链接器不会放过这个只有声明的空架子,但这不是一种好的解决方法。因为有这样一个编程的原则:错误越早被发现就越好。编译要早于链接,所以在编译发现错误要优于在链接阶段才发现的错误,可以节省时间,提高效率。

    下面是书上提到的一个应用:

    1 class Uncopyable
    2 {
    3 protected:
    4          Uncopyable(){}
    5          ~Uncopyable(){}
    6 private:
    7          Uncopyable(const Uncopyable&);
    8          Uncopyable& operator= (const Uncopyable&);
    9 };
    1 class HomeForSale: public Uncopyable
    2 {…};

    这样HomeForSale就不能被拷贝了。这里的继承可以不是public,比如private。

    一句话总结一下:为了驳回编译器自动提供的机能(比如可拷贝),可将相应的成员函数声明为private且不予实现。还有一种方法,继承Uncopyable也行。

  • 相关阅读:
    前端攻城狮学习笔记九:让你彻底弄清offset
    JavaScript中Element与Node的区别,children与childNodes的区别
    JavaScript代码优化实战之一:缓存变量,关键字过滤
    【转】纯CSS画的基本图形(矩形、圆形、三角形、多边形、爱心、八卦等),NB么
    包装对象——JavaScript中原始类型拥有属性的原因
    关于两个容积不同的瓶子中装水可以得到哪些精确值的问题的算法
    JavaScript中判断鼠标按键(event.button)
    累了休息一会儿吧——分享一个JavaScript版扫雷游戏
    用CSS让未知高度内容垂直方向居中
    空间换时间,把递归的时间复杂度降低到O(2n)
  • 原文地址:https://www.cnblogs.com/jerry19880126/p/2964846.html
Copyright © 2011-2022 走看看