继承使用时要注意,默认是私有派生。所以要公有派生时必须记得加关键字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来指示派生时,基类就称为了虚基类。其构造函数的规则有所变化,不会自动进行信息不换传递,需要显式地调用基类构造函数。

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

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

C++_代码重用4-多重继承的更多相关文章

  1. C++_代码重用1-总览

    C++的主要目的是促进代码重用. 公有继承是实现这一目标的机制之一: 本身是另一个类的成员,这种方法称为包含.组合.层次化. 另一种方法是使用私有.保护继承. 通常包含.私有继承和保护继承用于实现ha ...

  2. C++_代码重用5-类模板

    如果两种类只是数据类型不同,而其他代码是相同的,与其编写新的类声明,不如编写一种泛型(独立于类型的)栈.然后将具体的类型作为参数传递给这个类.这样就可以使用通用的代码生成存储不同类型值的栈. 可以使用 ...

  3. C++_代码重用3-私有继承

    使用包含:易于理解,类声明中包含表示被包含类的显式命名对象,代码可以通过名称引用这些对象: 使用继承:将使关系更抽象,且继承会引起很多问题,尤其是从多个基类继承时. 私有继承所提供的特性确实比包含多. ...

  4. C++_代码重用2-包含对象成员的类

    对于姓名可以使用字符数组来表示,但这将限制姓名的长度.当然,还可以使用char指针和动态内存分配,但这要求提供大量的支持代码.有一个好的方法就是使用一个他人开发好的类的对象来表示.如果C++库提供了合 ...

  5. Javascript中的Trait与代码重用

    Javascript中的Trait与代码重用 来源 http://www.ituring.com.cn/article/64103 我们知道,OOP中最普遍的代码重用方式是通过继承,但是,继承有一些缺 ...

  6. 《C++ Primer Plus》读书笔记之十二—C++中的代码重用

    第14章 C++中的代码重用 1.C++代码重用方法:公有继承.使用本身是另一个类的对象的类成员(这种方法称为包含.组合或层次化).私有或保护继承.类模板等. 2.模板特性意味着声明对象时,必须指定具 ...

  7. C++ primer plus读书笔记——第14章 C++中的代码重用

    第14章 C++中的代码重用 1. 使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现).获得接口是is-a关系的组成部分.而使用组合,类可以获得实现,但不能获得接口. ...

  8. “前.NET Core时代”如何实现跨平台代码重用 ——程序集重用

    除了在源代码层面实现共享("前.NET Core时代"如何实现跨平台代码重用 --源文件重用)之外,我们还可以跨平台共享同一个程序集,这种独立于具体平台的"中性" ...

  9. PHP代码重用与函数编写

    代码重用与函数编写 1.使用require()和include()函数 这两个函数的作用是将一个文件爱你载入到PHP脚本中,这样就可以直接调用这个文件中的方法.require()和include()几 ...

随机推荐

  1. libevent源码深度剖析八

    libevent源码深度剖析八 ——集成信号处理 张亮 现在我们已经了解了libevent的基本框架:事件管理框架和事件主循环.上节提到了libevent中I/O事件和Signal以及Timer事件的 ...

  2. Oracle设置主键自增长

    第一步:为表设置主键 第二步:新建序列 CREATE SEQUENCE SQ.SEQ_INCREASE  START WITH 12  MAXVALUE 999  MINVALUE 0 INCREME ...

  3. Mysql处理海量数据时的一些优化查询速度方法(转)

    最近一段时间由于工作需要,开始关注针对Mysql数据库的select查询语句的相关优化方法. 由于在参与的实际项目中发现当mysql表的数据量达到百万级时,普通SQL查询效率呈直线下降,而且如果whe ...

  4. 卡2-SLAM

    ---恢复内容开始--- 1.下载 首先需要从github上Git以下两个包: git clonehttps://github.com/ros-perception/open_karto(开源的kar ...

  5. 通过网页发布ios应用。

    原文地址:http://www.zhihu.com/question/24304345 两种方法: 1. 测试版本 支持任何类型的开发者帐号,需要在developer后台设置授权deviceID,可以 ...

  6. JavaScript 组件编写

    说明 这是一个联系人名过滤组件,还提供可选的"大小写是否敏感"选项,默认大小写不敏感. 一.HTML 结构 <ul class="contacts"> ...

  7. javascript总结7:算术运算符

    1  运算符: 加号+ 如果是数字类型的变量相加,那么结果为数字类型; 如果是非数字类型的变量相加,结果为字符串类型 2  减号- 如果是非数字类型的变量相减结果为  NaN 3 乘号 * 如果是非数 ...

  8. Build fat static library (device + simulator) using Xcode and SDK 4+

    155down votefavorite 185 It appears that we can - theoretically - build a single static library that ...

  9. 设计模式05: Prototype 原型模式(创建型模式)

    Prototype 原型模式(创建型模式) 依赖关系的倒置抽象不应该依赖于实现细节,细节应该依赖于抽象.对所有的设计模式都是这样的. -抽象A直接依赖于实现细节b -抽象A依赖于抽象B,实现细节b依赖 ...

  10. jquery中attr和prop的区别(转)

    在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很多.这里谈谈我的心得,我的心得很简单: ...