zoukankan      html  css  js  c++  java
  • Effective C++ 条款39 明智而审慎地使用private继承

    1. public继承表明is-a的关系,要求接口的完全继承,而private继承表明"根据某物实现出的关系",要求仅仅继承实现,private继承有两个规则:

        1). 经由private继承而来的基类的所有成员在派生类中都会变成private属性

        2). 由于1),编译器不允许将派生类转为基类以防止对派生类private成员的非法访问.

    2. 由条款38,private继承和复合具有相同作用——"根据某物实现出".两者之间,要尽可能使用复合,除非必要情况.必要情况指的是protected成员和virtual函数牵扯进的时候以及某个极端情况(稍后会说明)下空间限制严格的时候.

    复合对于private继承的优势:

    假设要实现一个Widget类,而它要用到一个Time类,也就是说,要"根据Time类实现Widget类",

    如果用private继承,可能像这样:

    class Widget:private Timer{
    public:
        ...
    private:
        ...
    }
    View Code

    如果用复合,可能像这样:

    class Widget{
    public:
        ...
    private:
        Time timer;
        ...
    }
    View Code

    (将timer设为private,因为Widget类并不打算对客户端开放Time的接口)

    有两个方面可以体现复合对于private继承的优势:

    1). private继承不能阻止Widget的派生类对timer的某个virtual函数进行重定义,这可能是Widget的设计者不想看到的.

    2). 继承提高了文件之间的编译依存性,因为Widget继承了Time,因而定义Widget的头文件需要include定义Time的头文件,而使用复合的话只需要将Widget内的Time替换为Time*即可

    当然,也有两种情况使用private继承更好:

    1). "当一个意欲成为derived class者想访问一个意欲成为base class者的protected部分,或为了重定义一或多个virtual函数,但这两个classes之间的概念关系其实是'is-implementations-in-terms-of'而非is-a"时.

    2). private继承可以使编译器进行EBO(empty base optimization,空白基类最优化),所谓空白基类最优化,即对于以下empty类:

    class Empty{
    }

    如果采用采用以下复合:

    class HoldsAnInt{
        int a;
        Empty e;
    }
    View Code

    那么一个HolderAsInt类将不止占据4字节(可能会占据8字节),因为对于"大小为零之独立(非附属)对象",C++标准要求安插一个char到其中以支持取址.(又由于字节对齐,HoldersAsInt可能会占据8字节)

    而如果采用private继承,一个HoldersAsInt仅需4字节,Empty对象将不再占据空间,即:

    class HoldersAsInt:private Empty{
        int a;
    }
    View Code

    这就是编译器实行的EBO.当然,现实中使用的"empty classes"并非真的什么都不包含,虽然它们没有non-static对象,但往往有typedefs,enum,static成员变量,或non-virtual函数(STL就有许多有技术用途的empty classes,其中内含有用的成员(通常是typedefs),包括base classes unary_function和binary_function,这些是"用户自定义之函数对象"通常会继承的classes,由于EBO,可以避免derived classes大小的增加).

    3. 总结:

        1). private继承和复合都意味着is-implementation-in-terms-of,但复合比较容易理解,优先选择复合.

        2). 面对并不存在is-a关系的两个类且其中一个需要访问另一个的protected成员或需要重新定义其virtual函数,private继承可能是最佳选择,此外,private复合所允许的EBO对致力于"对象尺寸最小化"的程序库开发者而言可能很重要.

  • 相关阅读:
    how to read openstack code: loading process
    how to read openstack code: request extension
    how to read openstack code: action extension
    b站刷赞 B站刷赞工具 bilibili评论刷赞 b站点赞
    利用邓西百度网盘消息群发工具对百度网盘的群组、好友进行管理,批量分享文件
    如何利用邓西百度网盘批量转存检测工具批量检测百度网盘失效分享链接
    如何使用邓西百度网盘批量重命名工具对百度网盘中的文件进行批量改名、删除等
    如何利用邓西百度网盘消息群发工具批量删除百度网盘单向好友
    如何利用工具自动通过百度网盘好友请求并发送消息或文件
    邓西百度网盘批量保存检测工具高级用法之分享链接以指定名称保存
  • 原文地址:https://www.cnblogs.com/reasno/p/4799345.html
Copyright © 2011-2022 走看看