zoukankan      html  css  js  c++  java
  • 【40】明智而审慎地使用多重继承

    1、多种继承,首先带来一个问题。那就是子类会从多个父类中继承相同的名称。这样,在调用的时候,必然导致歧义。

    2、考虑Base1中有个public方法XXX,Base2中有个private方法XXX,Derived继承Base1和Base2,那么分析一下,Derived d; d.XXX()到底调用哪个方法?

      你可能会想,虽然两个都匹配,但是只有Base1的XXX方法可访问,因此调用Base1的XXX方法。这种想法是错的,编译报错:对XXX的访问不明确。为什么?

      因为编译器决议调用哪个方法的时候,第一步,先把所有匹配的名称都拿来,不管是不是可以访问,然后在里面找到一个最优匹配,如果两个匹配程度一样,编译器就傻眼了,只能报错。再退一步说,C++过载不能跨域,即只能在当前类中过载。经过测试,从多个父类继承相同的名称,即使匹配程度不一样,也会导致对XXX的访问不明确。

      怎么解决这个问题呢?

      明确告诉编译器,我要调用哪个父类的方法。

      d.Base1::XXX(); //OK

      d.Base2::XXX(); //Error,无法访问成员XXX

      注:单一继承也可以使用d.Base1::XXX();这种形式。

      还有一个办法,子类定义一个XXX方法,隐藏两个父类的XXX方法,这样就不存在不明确的调用了。

    3、钻石型多继承,考虑InputFile继承File,OutputFile继承File,IOFile继承InputFile和OutputFile,File中有个数据fileName,现在出问题了。从继承角度讲,IOFile有两份fileName,但根据常识,IOFile应该只有一个fileName。C++默认的做法是IOFile中有两个fileName。

    4、如何解决上面的问题呢?也就是说,保证IOFile中只有一个fileName。通过使用virtual继承。让InputFile和OutputFile使用virtual继承,IOFile的继承方式不变。这样就使得IOFile中,只有一个fileName。显而易见,这种做法非常丑陋。而且,虽然起到了效果,要付出很大的代价。编译器在幕后做了一些事情,导致的结果是:InputFile的体积变大,访问变慢,初始化也可能带来诡异的问题。

    5、因此,尽量少使用virtual继承。如果必须使用virtual继承,也要保证不在virtual Base(即File)中放置数据,从而保证IOFile中没有重复的数据。C#和Java中的interface就不允许有数据。相对而言,有重复的方法,还好办,可以指定调用哪个父类的方法。

    6、那么,多重继承就一无是处吗?多重继承的使用场景:public继承一个类,暴露接口,同时private继承一个类,根据它来实现。你可能会想,根据某物实现出,不是应该优先使用复合技术吗?private继承可以解决两个问题:一是private继承可以访问protected成员,二是可以重写方法。

  • 相关阅读:
    hdu 4614 线段树 二分
    cf 1066d 思维 二分
    lca 最大生成树 逆向思维 2018 徐州赛区网络预赛j
    rmq学习
    hdu 5692 dfs序 线段树
    dfs序介绍
    poj 3321 dfs序 树状数组 前向星
    cf 1060d 思维贪心
    【PAT甲级】1126 Eulerian Path (25分)
    【PAT甲级】1125 Chain the Ropes (25分)
  • 原文地址:https://www.cnblogs.com/nzbbody/p/3504283.html
Copyright © 2011-2022 走看看