C++_代码重用4-多重继承
继承使用时要注意,默认是私有派生。所以要公有派生时必须记得加关键字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-多重继承的更多相关文章
- C++_代码重用1-总览
C++的主要目的是促进代码重用. 公有继承是实现这一目标的机制之一: 本身是另一个类的成员,这种方法称为包含.组合.层次化. 另一种方法是使用私有.保护继承. 通常包含.私有继承和保护继承用于实现ha ...
- C++_代码重用5-类模板
如果两种类只是数据类型不同,而其他代码是相同的,与其编写新的类声明,不如编写一种泛型(独立于类型的)栈.然后将具体的类型作为参数传递给这个类.这样就可以使用通用的代码生成存储不同类型值的栈. 可以使用 ...
- C++_代码重用3-私有继承
使用包含:易于理解,类声明中包含表示被包含类的显式命名对象,代码可以通过名称引用这些对象: 使用继承:将使关系更抽象,且继承会引起很多问题,尤其是从多个基类继承时. 私有继承所提供的特性确实比包含多. ...
- C++_代码重用2-包含对象成员的类
对于姓名可以使用字符数组来表示,但这将限制姓名的长度.当然,还可以使用char指针和动态内存分配,但这要求提供大量的支持代码.有一个好的方法就是使用一个他人开发好的类的对象来表示.如果C++库提供了合 ...
- Javascript中的Trait与代码重用
Javascript中的Trait与代码重用 来源 http://www.ituring.com.cn/article/64103 我们知道,OOP中最普遍的代码重用方式是通过继承,但是,继承有一些缺 ...
- 《C++ Primer Plus》读书笔记之十二—C++中的代码重用
第14章 C++中的代码重用 1.C++代码重用方法:公有继承.使用本身是另一个类的对象的类成员(这种方法称为包含.组合或层次化).私有或保护继承.类模板等. 2.模板特性意味着声明对象时,必须指定具 ...
- C++ primer plus读书笔记——第14章 C++中的代码重用
第14章 C++中的代码重用 1. 使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现).获得接口是is-a关系的组成部分.而使用组合,类可以获得实现,但不能获得接口. ...
- “前.NET Core时代”如何实现跨平台代码重用 ——程序集重用
除了在源代码层面实现共享("前.NET Core时代"如何实现跨平台代码重用 --源文件重用)之外,我们还可以跨平台共享同一个程序集,这种独立于具体平台的"中性" ...
- PHP代码重用与函数编写
代码重用与函数编写 1.使用require()和include()函数 这两个函数的作用是将一个文件爱你载入到PHP脚本中,这样就可以直接调用这个文件中的方法.require()和include()几 ...
随机推荐
- 4-3 线程安全性-原子性-synchronized
原子性它提供了互斥访问,同一时刻只能有一个线程来对它进行操作.能保证同一时刻只有一个线程来对其进行操作的,除了Atomic包之外,还有锁.JDK提供锁主要分两种,synchronized是一个Java ...
- Java 基于web service 暴露接口 供外部调用
package cn.zr.out.outinterface; import java.text.SimpleDateFormat; import java.util.Date; import jav ...
- 【Docker官方文档】理解Docker
本文来自Docker的官方文档,详细介绍了Docker的体系结构.重要概念.内部工作机理等内容,推荐不了解Docker内部原理的同学阅读. 什么是Docker? Docker是一个用于开发.交付和运行 ...
- Linux pkg-config命令
一.简介 pkg-config用来检索系统中安装库文件的信息.典型的是用作库的编译和连接. 二.实例 http://blog.chinaunix.net/uid-20595934-id-1918368 ...
- Java方法学习疑问
此方法不理解 finalize() 方法 Java允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做finalize( ),它用来清除回收对象. 例如,你可以使用finaliz ...
- 453D Little Pony and Elements of Harmony
传送门 分析 我们可以将所有的b[i^j]直接对应到b[f(i^j)]上 于是显然可以fwt 我们对b进行t次fwt之后直接将答案与e0卷起来即可 注意由于模数不确定,我们可以将模数扩大$2^m$然后 ...
- The Difference Between @Helpers and @Functions In WebMatrix
from: http://www.mikesdotnetting.com/article/173/the-difference-between-helpers-and-functions-in-web ...
- Java IO RandomAccessFile 任意位置读/写
随机读写类 RandomAccessFile的唯一父类是Object,与其他流父类不同.是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必 ...
- POJ - 2109 Power of Cryptography(高精度log+二分)
Current work in cryptography involves (among other things) large prime numbers and computing powers ...
- NSStream文件流
1.文件流的使用 NSString *filePath = @"/Users/JHQ0228/Desktop/test.txt"; NSData *data = [@"h ...