• Effective C++ 精要(第六部分:继承与面向对象设计)


    条款32:确定你的public继承塑模出is-a关系


    条款33:避免遮掩继承而来的名称

    name hiding其实是和作用域有关的话题, 但是它在继承体系中有些更微妙的东西。我们知道在一个函数中如果有个local 变量x,同时函数外还有个变量x,那在这个函数中看到的x是函数内的local变量x。也就是local变量hide了全局变量,这个是C语言中的name hiding。下面看继承时的情况,其实从编译器的角度看,就是Base类的作用域比子类的要大,当在子类中定义了一个symbol时,会hide基类中同名的symbol。我们这里说symbol就是说它无关于这个symbol是什么类型,int?double?virtual函数?non-virtual函数?都无所谓的,关键就是看其名字是不是一样的。

    image

    为了更好的说明这个问题,看下面的图:

    image

    子类中的mf1会遮盖掉在基类中的mf1,包括那个带int参数的;mf3会遮盖基类中的mf3,是的,两个都被遮盖了。如果我们想把所有名为mf1的声明式都带到子类中,可以在子类中使用using Base::mf1,这时就所有的mf1就在子类中可见,并且为public。但如果你只是想把某一个名为mf3的函数带到子类中,其他就不想这样做,比如在private继承时,我们唯一想继承的是某个版本的mf3,我们可以使用一个forwarding函数来做这个事情。

    条款34:区分接口继承和实现继承

    说到继承,我们可能会想做的事情包括:希望子类只继承基类的接口;有时希望子类同时继承接口和实现,但又希望能override它们所继承的实现;而有时候你希望子类继承基类的接口和实现,并且不允许override任何东西。

    • 如果是只继承接口,可以把基类中的函数做成纯虚函数,我们可以为纯虚函数提供一份实现代码;
    • 如果是同时继承接口和缺省实现,就应该选用impure virtual函数;【但允许impure virtual函数同时提供接口和缺省实现,会造成问题,比如书中例子,飞机A和B继承了基类的默认fly(),但是新进的机型C的fly()应该有不同的实现,但因为匆忙而没有实现,这时C就会使用基类的默认实现,这会引起灾难的,解决的办法有几个:1. 将fly接口仍然设计成纯虚函数,同时提供一个non-virtual 的protected函数提供缺省实现defaultFly(),强制要求子类实现fly(),如果子类使用缺省实现,就可以直接调用defaultFly(),而如果不用缺省实现,就可以另外实现,因为fly()是纯虚函数,客户必须实现,从而避免了出错的可能性。2. 利用纯虚函数可以有一份实现代码这个特点,在子类的实现中调用父类的缺省实现,或者额外实现】
    • 如果要子类继承函数的接口和一份强制实现,并不允许override,可以声明为一个non-virtual函数。non-virtual函数的意义是不变性凌驾于特异性。


    条款35:考虑virtual函数以外的其他选择

    除了virtual函数,还有其他方式实现多态。比如NVI、Function Pointer和tr1::function。

    • NVI方式是,定义一个non-virtual public成员函数,这个成员函数调用private virtual函数(为什么是private virtual呢?private是因为这份实现不希望被子类继承,virtual是因为,当对子类对象调用non-virtual public函数时,该函数调用的private virtual函数是子类实现的函数,也就是多态了);
    • function Pointer方式:用一个function Pointer作为参数传给类的构造函数,类之后使用这个function Pointer执行某个动作;
    • tr1::function:类似于function Pointer的方式,不过tr1::function更加强大,可以有更多灵活性;
      条款36:绝不重新定义继承而来的non-virtual函数


    条款37:绝不重新定义继承而来的缺省参数值

    virtual函数的缺省参数值是静态绑定的,重新定义只会造成混乱。


    条款38:通过复合塑模出has-a或"根据某物实现出"


    条款39:明智而审慎地使用private继承


    条款40:明智而审慎地使用多重继承

  • 相关阅读:
    linux下vim命令详解
    Linux 指令篇:档案目录管理chown
    分级渲染百度地图路段红黄绿功能
    矢量数据的属性值的添加、编辑、删除
    Extjs+C# 文件上传
    IBATIS 的动态SQL语句拼接
    一个DIV位于另一个div的右下角
    ArcGIS JavaScript API 添加点
    将Excel数据导入至SqlServer中
    Extjs 图表控件,可修改X轴与Y轴坐标
  • 原文地址:https://www.cnblogs.com/whyandinside/p/2755070.html
Copyright © 2020-2023  润新知