虚继承与虚基类的本质

上传人:桔**** 文档编号:467346700 上传时间:2023-08-23 格式:DOCX 页数:14 大小:19.58KB
返回 下载 相关 举报
虚继承与虚基类的本质_第1页
第1页 / 共14页
虚继承与虚基类的本质_第2页
第2页 / 共14页
虚继承与虚基类的本质_第3页
第3页 / 共14页
虚继承与虚基类的本质_第4页
第4页 / 共14页
虚继承与虚基类的本质_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《虚继承与虚基类的本质》由会员分享,可在线阅读,更多相关《虚继承与虚基类的本质(14页珍藏版)》请在金锄头文库上搜索。

1、 虚继承与虚基类的本质 虚继承和虚基类的定义是非常的简朴的,同步也是非常容易判断一种继承与否是虚继承的,虽然这两个概念的定义是非常的简朴明确的,但是在C+语言中虚继承作为一种比较生僻的但是又是绝对必要的构成部份而存在着,并且其行为和模型均体现出和一般的继承体系之间的巨大的差别(涉及访问性能上的差别),目前我们就来彻底的从语言、模型、性能和应用等多种方面对虚继承和虚基类进行研究。 一方面还是先给出虚继承和虚基类的定义。 虚继承:在继承定义中涉及了virtual核心字的继承关系; 虚基类:在虚继承体系中的通过virtu继承而来的基类,需要注意的是:uct CSbClass :publicirtal

2、 Base ;其中Cse称之为CSubClas 的虚基类,而不是说CBa就是个虚基类,由于Ba还可以不不是虚继承体系中的基类。 有了上面的定义后,就可以开始虚继承和虚基类的本质研究了,下面按照语法、语义、模型、性能和应用五个方面进行全面的描述。 1. 语法 语法有语言的自身的定义所决定,总体上来说非常的简朴,如下: tt CSubCla : publc virulCBseClass ;其中可以采用puic、potected、ivte三种不同的继承核心字进行修饰,只要 保证涉及viua就可以了,这样一来就形成了虚继承体系,同步aelas就成为了CSuClas的虚基类了。 其实并没有那么的简朴,如

3、果浮现虚继承体系的进一步继承会浮现什么样的状况呢? 如下所示: / * 带有数据成员的基类* stuct CBaeCss1 CBaseCls1(size_ i):m_val(i ) sie_t ma; ; * 虚拟继承体系*/ srt CSublassV :puic virtualCBaseCls1 SubCassV1( ize_ti) : BaeClas( i ) ; truct CSublssV: puvrtu CBaseClss1 CubClass2(se_ti) : aseClss1( i ) ; stut CDiaondClss1 :public CSulassV1, publicC

4、SubClasV2 DimondCass1( sze_ i ) : CBsCas1(i ), CSuClassV1( i), CubClssV2( ) ; suctCiamonSubls1 : public CDimondClass1 DiamndSbCla1(size_): aseCss1( i ), CDimondlss( i) ; 注意上面代码中的CDiamndClass1和CDiamndubClass1两个类的构造函数初始化列 表中的内容。可以发现其中均涉及了虚基类CBsass1的初始化工作,如果没有这 个初始化语句就会导致编译时错误,为什么会这样呢?一般状况下不是只要在 CSuCla

5、和CSubClassV2中涉及初始化就可以了么?要解释该问题必须要明白虚 继承的语义特性,因此参看下面语义部分的解释。 2. 语义 从语义上来讲什么是虚继承和虚基类呢?上面仅仅是从如何在C+语言中书写合法的 虚继承类定义而已。一方面来理解一下irt这个核心字在C+中的公共含义,在C 语言中仅仅有两个地方可以使用virtal这个核心字,一种就是类成员虚函数和这里 所讨论的虚继承。不要看这两种应用场合仿佛没什么关系,其实她们在背景语义上 具有vitul这个词所代表的共同的含义,因此才会在这两种场合使用相似的核心字。那么rtul这个词的含义是什么呢? vitul在美国老式词典双解中是这样定义的: a

6、dj.(形容词) 1 Existng orsltng i esenc or effect though ot i ca fct,fo, or nae: 实质上的,事实上的:虽然没有实际的事实、形式或名义,但在事实上或效 果上存在或产生的; .Eisigin the mind, espealy as poctof teimgiatin. sedin ltearcicism otet. 虚的,内心的:在头脑中存在的,尤指意想的产物。用于文学批评中。 我们采用第一种定义,也就是说被virtual所修饰的事物或现象在本质上是存在的, 但是没有直观的形式体现,无法直接描述或定义,需要通过其她的间接方式或

7、手段 才可以体现出其事实上的效果。 那么在C+中就是采用了这个词意,不可以在语言模型中直接调用或体现的,但是确 实是存在可以被间接的方式进行调用或体现的。例如:虚函数必须要通过一种间接的 运营时(而不是编译时)机制才可以激活(调用)的函数,而虚继承也是必须在运营时才可以进行定位访问的一种体制。存在,但间接。其中核心就在于存在、间接和共 享这三种特性。 对于虚函数而言,这三个特性是较好理解的,间接性表白了她必须在运营时根据实际的对象来完毕函数寻址,共享性表象在基类会共享被子类重载后的虚函数,其实指向 相似的函数入口。 对于虚继承而言,这三个特性如何理解呢?存在即表达虚继承体系和虚基类的确存在,

8、间接性表白了在访问虚基类的成员时同样也必须通过某种间接机制来完毕(下面模型 中会讲到),共享性表象在虚基类会在虚继承体系中被共享,而不会浮现多份拷贝。 那目前可以解释语法小节中留下来的那个问题了,“为什么一旦浮现了虚基类,就必 须在没有一种继承类中都必须涉及虚基类的初始化语句”。由上面的分析可以懂得, 虚基类是被共享的,也就是在继承体系中无论被继承多少次,对象内存模型中均只会 浮现一种虚基类的子对象(这和多继承是完全不同的),这样一来既然是共享的那么 每一种子类都不会独占,但是总还是必须要有一种类来完毕基类的初始化过程(由于 所有的对象都必须被初始化,哪怕是默认的),同步还不可以反复进行初始化

9、,那到底谁应当负责完毕初始化呢?C+原则中(也是很自然的)选择在每一次继承子类中 都必须书写初始化语句(由于每一次继承子类也许都会用来定义对象),而在最下层 继承子类中实际执行初始化过程。因此上面在每一种继承类中都要书写初始化语句, 但是在创立对象时,而仅仅会在创立对象用的类构造函数中实际的执行初始化语句,其她的初始化语句都会被压制不调用。 3. 模型 为了实现上面所说的三种语义含义,在考虑对象的实现模型(也就是内存模型)时就 很自然了。在C+中对象事实上就是一种持续的地址空间的语义代表,我们来分析虚 继承下的内存模型。3. 存在 也就是说在对象内存中必须要涉及虚基类的完整子对象,以便可以完毕

10、通过地址完毕对象的标记。那么至于虚基类的子对象会寄存在对象的那个位置(头、中间、 尾部)则由各个编译器选择,没有差别。(在VC中无论虚基类被声明在什么位置, 虚基类的子对象都会被放置在对象内存的尾部) .2. 间接 间接性表白了在直接虚基承子类中一定涉及了某种指针(偏移或表格)来完毕通 过子类访问虚基类子对象(或成员)的间接手段(由于虚基类子对象是共享的, 没有拟定关系),至于采用何种手段由编译器选择。(在C8中在子类中放置了 一种虚基类指针vbc,该指针指向虚函数表中的一种slo,该so中寄存则虚基 类子对象的偏移量的负值,事实上就是个以补码表达的int类型的值,在计算虚 基类子对象首地址时

11、,需要将该偏移量取绝对值相加,这个重要是为了和虚表 中只能寄存虚函数地址这一规定相区别,由于地址是原码表达的无符号i类型 的值) 3.3. 共享 共享表白了在对象的内存空间中仅仅可以涉及一份虚基类的子对象,并且通过 某种间接的机制来完毕共享的引用关系。在简介完整个内容后会附上测试代码, 体现这些内容。 4 性能 由于有了间接性和共享性两个特性,因此决定了虚继承体系下的对象在访问时必然 会在时间和空间上与一般状况有较大不同。 4.时间 在通过继承类对象访问虚基类对象中的成员(涉及数据成员和函数成员)时,都 必须通过某种间接引用来完毕,这样会增长引用寻址时间(就和虚函数同样), 其实就是调节thi指针以指向虚基类对象,只但是这个调节是运营时间接完毕的。 (在C8中通过打开汇编输出,可以查看*co文献中的内容,在访问虚基类对象 成员时会形成三条mov间接寻址语句,而在访问一般继承类对象时仅仅只有一条ov常量直接

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 解决方案

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号