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对致力于"对象尺寸最小化"的程序库开发者而言可能很重要.

  • 相关阅读:
    SQL Server 2005 学习笔记之触发器简介[转]
    什么是BCD 码
    关于C# 中的Attribute 特性
    也谈Asp.net 中的身份验证
    SQL Server 2005 创建分区表
    使用SerialPort 对象实现串口拨号器通信[下]
    子角色权限的实现
    SQL Server 中,实现 varbinary 与 varchar 类型之间的数据转换
    TSQL 常用排名函数
    关于ASP.NET 将数据导出成Excel 的总结[中]
  • 原文地址:https://www.cnblogs.com/reasno/p/4799345.html
Copyright © 2011-2022 走看看