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成员,二是可以重写方法。

  • 相关阅读:
    Kubernetes实战:高可用集群的搭建和部署
    华为云MVP程云:知识化转型,最终要赋能一线
    支持60+数据传输链路,华为云DRS链路商用大盘点
    关于单元测试的那些事儿,Mockito 都能帮你解决
    深入原生冰山安全体系,详解华为云安全服务如何构筑全栈安全
    云小课|ModelArts Pro 视觉套件:零代码构建视觉AI应用
    FLINK重点原理与机制:内存(1)task之间的数据传输
    FLINK重点原理与机制:内存(2)网络流控及反压机制剖析(一)
    FLINK重点原理与机制:状态(3)两阶段提交
    FLINK重点原理与机制:状态(2)Flink的检查点算法CHECKPOINT
  • 原文地址:https://www.cnblogs.com/nzbbody/p/3504283.html
Copyright © 2011-2022 走看看