族谱网 头条 人物百科

多重继承

2020-10-16
出处:族谱网
作者:阿族小谱
浏览:470
转发:0
评论:0
争议多重继承可以导致某些令人混淆的情况,所以关于它的好处与风险之间孰轻孰重常常受人争论。Java使用了一个折衷的办法:Java允许一个类别继承自多于一个父接口(可以指定某一个类别,它继承了所有父类别的类型,并必须拥有所有父类别接口的外部可见方法的具体实现,并允许编译器强制以上要求),但只可以从一个父类别继承实现(方法与数据)。微软的.NET编程语言,例如C#和VisualBasic.NET也使用了这种接口的做法。面向对象的程序设计中,继承描述了两种类型或两个类的对象,其中一种是另外一种的“子类型”或“子类”。子类继承了父类别的特征,允许分享功能。例如,可以创造一个“哺乳类动物”类别,拥有进食、繁殖等的功能;然后定义一个子类型“猫”,它可以从父类别继承上述功能,不需重新编写程序,同时增加属于自己的新功能,例如“追赶老鼠”。然而,如果想同时自多于一个结构继承,例如容许“猫”继承“哺乳类动物”之...

争议

多重继承可以导致某些令人混淆的情况,所以关于它的好处与风险之间孰轻孰重常常受人争论。Java使用了一个折衷的办法:Java允许一个类别继承自多于一个父接口(可以指定某一个类别,它继承了所有父类别的类型,并必须拥有所有父类别接口的外部可见方法的具体实现,并允许编译器强制以上要求),但只可以从一个父类别继承实现(方法与数据)。微软的.NET编程语言,例如C#和Visual Basic .NET也使用了这种接口的做法。

面向对象的程序设计中,继承描述了两种类型或两个类的对象,其中一种是另外一种的“子类型”或“子类”。子类继承了父类别的特征,允许分享功能。例如,可以创造一个“哺乳类动物”类别,拥有进食、繁殖等的功能;然后定义一个子类型“猫”,它可以从父类别继承上述功能,不需重新编写程序,同时增加属于自己的新功能,例如“追赶老鼠”。

然而,如果想同时自多于一个结构继承,例如容许“猫”继承“哺乳类动物”之余,同时继承“卡通角色”和“宠物”,缺乏多重继承往往会导致十分笨拙的混合继承,或迫使同一个功能在多于一个地方被重写。(这带来了维护上的问题)

多年以来,多重继承都是一个敏感的话题,反对者指它增加了程序的复杂性与含糊性,例如在“钻石问题”(或称菱型缺陷)中。Loki库针对多重继承进行改良,以TypeList(二叉树结构)避免这个问题。

各种编程语言有不同的方式处理上述问题。例如Eiffel容许子类型通过重命名,或提前为他们确定选择规则,来适应(adapt)它继承得来的功能。Java允许对象从多个接口继承,但仅允许一个实现继承。REALbasic与它相似,并增加了一个不需使用继承来“扩展”一个类别的功能。Perl使用一种有序列表式的继承机制:搜索方法时,它会先搜索当前类别的方法,然后使用深度优先搜索来顺序查找各个继承类别及其父类别。CLOS允许程序设计者完全控制方法的组合。如果这还不足够,元对象协议给程序设计者一种手段去修改继承,方法调度,类别特例化,及其它内部的机制,而不影响系统的稳定性。

C++与多继承

C++支持多重继承,允许对现实世界进行更直接的建模,Borland C++的OWL Framework大量使用多重继承来描述视窗的关系。微软的MFC仅使用单一继承描述视窗,ATL使用多重继承实现COM/ActiveX,WTL则使用多重继承实现视窗。

多重继承与被覆盖的虚函数

对于最左基类,虚函数的覆盖与单继承情形一致。

对于非最左的基类,虚函数仍然可能会被派生类的成员函数覆盖。

成员函数中this指针调整

一个类的非静态成员函数,一般需要使用类对象的this指针来访问类数据成员。程序加载到内存后,成员函数代码占据了一块内存空间。成员函数并不知道自身是作为一个单独的(或最派生)类的直接成员函数,还是作为一个被派生的基类的成员函数而存在。实际上在内存空间的非静态成员函数,可能会同时是单独的(或最派生)类的直接成员函数与被派生的基类的成员函数。非静态成员函数也仅知道声明了该函数的类的数据成员的空间分布,不可能知道以该类为基类的派生类的数据成员的空间分布。因此调用非静态成员函数时,调用者有责任传给成员函数正确的this指针,即令this指针指向声明了该成员函数的类的对象开始地址。

对于单继承,派生类与基类的对象开始地址是一样的,因此调用非静态成员函数不需要调整this指针。对于多继承,调用不是最左基类的非静态成员函数时,调用者必须先调整this指针。这又分为两种情形:

一是非虚函数,在函数调用现场直接调整this的值。这是编译器根据多重继承的派生类的实例对象或指针在编译时就能确定的。例如:

structbase1{intv1;voidfoo1(int){}}structbase2{intv2;voidfoo2(int){}}structderive:base1,base2{};derived;intmain(){derive*p=&d;d.foo2(101);/* 上述调用语句编译后为:push 65h ;参数101压栈lea ecx,offset d+4 ;根据thiscall调用协议,ecx保存了this的值call base2::foo2 (1181145h)*/p->foo2(102);}

二是虚函数情形。因为虚函数的开始地址必须存放在虚表条目中,所以多重继承的派生类对非最左基类的被覆盖(override)的虚函数,在该派生类的相应的虚表条目中填写的是一个桩(thunk)地址。该桩通常只有两条机器指令,首先是调整this值(即修改ecx寄存器),然后是调用指令(call)。

参考文献

Andrei Alexandrescu. Modern C++ Design

参见

虚拟继承


免责声明:以上内容版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。感谢每一位辛勤著写的作者,感谢每一位的分享。

——— 没有了 ———
编辑:阿族小谱
发表评论
写好了,提交
{{item.label}}
{{commentTotal}}条评论
{{item.userName}}
发布时间:{{item.time}}
{{item.content}}
回复
举报
点击加载更多
打赏作者
“感谢您的打赏,我会更努力的创作”
— 请选择您要打赏的金额 —
{{item.label}}
{{item.label}}
打赏成功!
“感谢您的打赏,我会更努力的创作”
返回

更多文章

更多精彩文章
打赏
私信

推荐阅读

· 多重
外部链接ExamplesofusingCEMENTHowtomultipleexposewithanAPScameraHowtomultipleexposewithany35mmcameraDigitalnoisereductionbydoubleexposure
· 本多重次
生平相比起本名重次,因为通称作左卫门和勇猛果敢的刚毅性格,“鬼作左”的通称更为人所知。与天野康景、高力清长一同在德川家康三河时代起就是“三河三奉行”中的一人,发挥行政能力。与鬼的名号相似,在法理上是相当讲究的人,因而对他人非常严格(觉得不对的时候,即使是对着主君家康亦会激烈地指摘),但是在恩赏上也很公平清廉,以仮名写下法令并向民众解释,令民众容易理解。担任奉行期间,残忍的事不做,不偏袒徇私,明白地执行命令,处事明快而令人惊艳。不单是只有作为奉行行政的功绩,永禄元年(1558年)家康的寺部城初阵时,就建立军功,后来在三河一向一揆镇压战等战斗中也非常活跃并立下战功。而且在小田原征伐中,与向井正纲一同迎击梶原景宗率领的北条水军并将其击破。但是在小田原征伐结束后,自从家康被移封至北条氏的旧领关东后,因为家康受到丰臣秀吉的命令,重次被命令蛰居在上总国古井户(小糸,现今的千叶县君津市)领有3千石。后来
· 多重线性映射
例子在实数域上的内积(点积)是两个变量的对称双线性函数,矩阵的行列式是方矩阵的列(或行)的斜对称多重线性函数。矩阵的迹数是方矩阵的列(或行)的多重线性函数。双线性映射是多重线性映射。在n×n矩阵上多重线性映射可以考虑在有单位元的交换环K上的n×n矩阵上的多重线性函数为矩阵的行(或等价说列)上的函数。设A是这样的矩阵而ai{\displaystylea_{i}},1≤i≤n是A的行。则多重线性函数D可以写为满足如果我们设εε-->j{\displaystyle\varepsilon_{j}}表示单位矩阵的第j行,我们用下列方法表示ai{\displaystylea_{i}}利用D的多线性我们重写D(A)为继续这种代换于每个ai{\displaystylea_{i}}我们得到,对于1≤i≤n所以D(A)是唯一的决定自它如何运算于D(εε-->k1,……--&...
· 中华王姓的多重姓源
华夏族具有并包兼容的性格,千百年来,不同文化支流的融汇交合,溶聚成了今天深邃浩瀚的中华文化大流。作为中华排行第一或第二大姓的“王”姓,在其千百年的发展史中,同样融汇交合了不同的血缘流脉。显赫大姓有着多重来源,同姓不一定同宗,同宗不一定同姓。姓氏不仅是一个血缘符号,更是一个文化符号、历史符号……(一)名符其实的“王者之后”从字源角度分析,“王”字乃指至高无上的权贵之士,特指君王;而“王”姓,名符其实,正是“王者之后,具有极为高贵的身世源流。中国具有5000年悠久的历史,自从盘古开天地,三皇五帝到如今,不知出现过多少为王为帝者;而王姓的来源,正是那些王子王孙以“王”为氏,标榜其天潢帝胄的出身而来的。王子成父或太子晋的后裔,以王为氏,这是王姓中国人的主要源流,史称“姬姓王氏”,约占全球一亿多王氏人口的十之八、九。除此之外,以王为氏者还有以下数途:1、姬姓京兆王氏。姬姓之王的另一支京兆王、河间王为...
· 多重编程范式
两种模态的语言可视化、数据流函数式、逻辑面向对象,函数式函数式,可视化面向对象(基于类),可视化11种模态的编程语言Mathematica

关于我们

关注族谱网 微信公众号,每日及时查看相关推荐,订阅互动等。

APP下载

下载族谱APP 微信公众号,每日及时查看
扫一扫添加客服微信