继承使用时要注意,默认是私有派生。所以要公有派生时必须记得加关键字Public。

MI(Multi Inheritance)会带来哪些问题?以及如何解决它们?

两个主要问题:

从两个不同的基类继承同名方法;

从两个或更多相关基类那里继承同一个类的多个实例;

虚方法

Worker公有派生出Singer和Waiter;

然后Singer和Waiter公有派生出SingingWaiter(即多重继承);

这样会导致一个问题,就是SingingWaiter中有两个Worker组件。通常可以将派生类对象的地址赋值给基类指针。但是在这样的情况下这么做的话,将出现二义性。所以必须使用类型转换来指定对象。但这又增加了指针引用的复杂度。

C++在引入多重继承的同时,也引入新技术——虚基类,来解决该问题。

虚基类也用关键字virtual,虚基类与虚函数之间并不存在明显的联系。这么做是为了给程序员减少压力,类似于关键字的重载。

class Singer: virtual public Worker{…};

class Waiter: public virtual Worker{…};

(virtual和public的次序无关紧要)

那么为什么不使虚行为成为MI的默认准则呢?

在一些情况下,可能需要基类的多个拷贝;

将基类作为虚的要求程序完成额外的计算,为不需要的程序付出代价是不应当的;

新的构造函数规则

使用虚基类时,必须对构造函数采用新的方法;

对于非虚基类,唯一可以出现在初始化列表中的构造函数是即时基类构造函数。

A派生B,B派生C;--->C类的构造函数只能调用B类的构造函数,B类的构造函数只能调用A类构造函数。

但对于虚基类而言,这种信息自动传递方式不可用。这是因为对于多重继承而言,信息传递将通过两条不同的途径。为避免这种冲突,当基类是虚的,将禁止信息通过中间类自动传递给基类。

这就要求显式地调用所需的基类构造函数:

SingingWaiter(参数列表):Worker(wk),Waiter(wk,p),Singer(wk,v) { }

上述格式对虚基类来说是合法的,对非虚基类来说是非法的。

哪个方法

对于多重继承,如果每个祖先都有一个Show函数,那么会导致函数调用的二义性

对于单继承,如果没有重新定义show,将调用最近祖先中的show定义。

有几种解决方法:

1使用作用域解析运算符来澄清编程者的意图;

2或是在多重继承的类中重新定义show方法,并指出要使用哪个show;

这种递增的方法对于单继承来说是有效的;

但是对于多重继承来说,还是有问题:

SingingWaiter::Show

{Singer::Show();Waiter::Show();} //这将显示姓名和ID两次。

该如何解决呢?->使用模块化方法,而不是递增的方法;即提供一个只显示worker组件的方法,提供一个只显示waiter组件及singer组件的方法。

将所有数据组件都设置为保护的方法,而不是私有的,可以更严格地控制对数据的访问;

如果数据组件的方法是保护的,则只能在继承层次结构中的类中使用它,在其他地方则不能使用。

MI小结

MI会增加编程的复杂度。然而,这种复杂度主要是由于派生类通过多条途径继承同一个基类引起的。

当派生类使用关键字virtual来指示派生时,基类就称为了虚基类。其构造函数的规则有所变化,不会自动进行信息不换传递,需要显式地调用基类构造函数。

通过优先规则解决名称二义性。如果一个类从两个不同的类那里继承了两个同名的成员,则需要在派生类中使用类限定符来区分它们。否则,编译器将指出二义性。

有间接虚基类的派生类包含直接调用间接基类构造函数的构造函数,这对于间接非虚基类来说是非法的。

最新文章

  1. Hyper-V3:虚拟机的配置
  2. 前端福利!10个短小却超实用的JavaScript 代码段
  3. GOF业务场景的设计模式-----工厂模式
  4. mysqli 操作数据库(转)
  5. zz linux 下查看局域网内所有存活主机和MAC进址
  6. Java异常错误的面试题及答案
  7. debian安装jdk6
  8. HTML+CSS-采用DIV+CSS布局的利弊
  9. HDU2159--二维费用背包,三重背包
  10. PyQt4 的事件与信号 -- 重写事件处理方法
  11. toString()方法细节
  12. gitlab-ci + k8s 之docker (三)
  13. Apktool的安装与使用
  14. HDU - 5419 Victor and Toys(组合计数)
  15. fastdfs+nginx集群高可用搭建的一些坑!!记录一下
  16. DataTableHelper
  17. stl中的for_each() 函数的注意事项
  18. struts的理解
  19. Java命令学习系列(五)——jhat
  20. HDU 1012 u Calculate e(简单阶乘计算)

热门文章

  1. 10-编译PHP并与nginx整合
  2. google/dense_hash_map
  3. zend studio 字体大小修改,默认编码设置
  4. 557. Reverse Words in a String III 翻转句子中的每一个单词
  5. Linux查看操作系统版本的几种方式
  6. .net对Cookie的简单操作
  7. (转)mongodb学习(翻译1)
  8. Alpha项目复审
  9. vba实现excel多表合并
  10. js 去空格 和 获得字节数