码迷,mamicode.com
首页 > 编程语言 > 详细

深度探索C++关键字之 virtual

时间:2016-04-18 15:41:58      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:virtual 继承 多态 模型

    virtual在C++中有两个重要的用途:一是解决由多继承中父类有相同基类引起的子类中成员的二义性问题,二是实现多态。


一、解决二义性

    1、引起二义性的原因

    二义性是在多继承中出现的,如果父类继承了同一个基类,那么在派生类中成员遍会出现二义性。如下图所示:

技术分享

    派生类Derive的父类Base1和Base2都继承了同一个基类Base,在派生类Derive中,Base的成员_b被继承了两次,在访问成员_b时会出现二义性,因为无法确定访问继承自Base1中的_b还是访问继承自Base2中的_b。


2、引入虚拟继承,解决二义性问题

    让Base1和Base2虚拟继承Base,就可以解决Deriver中_b的二义性问题。代码如下:

class Base
{
public:
	int _b;
};

class Base1 :virtual public Base
{
public:
	int _b1;
};

class Base2 :virtual public Base
{
public:
	int _b2;
};

class Derive :public Base1, public Base2
{
public:
	int _d;
};

    虚拟继承是如何解决二义性呢?先来看一下Base1直接继承Base和虚拟继承Base模型发生了哪些变化。如下图所示:

技术分享

    由上图可以看出,当Base1虚拟继承Base后,Base1前四字节存放了一个地址,通过这个地址可以找到Base中成员相对于存放这个地址空间的偏移,进而找到Base中的成员。

    当Deriver继承了Base1和Base2后,Deriver的模型如下:

技术分享

    当Base1和Base2虚拟继承了Base后,Deriver继承Base1和Base2就不会出现二义性的问题。因为Base的成员_d在Deriver中只保留了一份,而Base1和Base2中本来属于_b的空间被放了两个地址,通过这个地址可以找到_b相对于当前位置的偏移,进而找到_b。


    ▲当一个基类由多个派生类时,这些派生类在继承基类时最好使用虚拟继承,以防某个类继承多个这些派生类时,产生二义性。


3、深度剖析virtual

    在学习这部分知识时,一起学学习的同学问了我一个问题,在菱形继承中(也就是上举的的例子),在哪要虚拟继承?在Deriver继承Base1和Base2时要不要虚拟继承?只在Deriver继承Base1和Base2时虚拟继承行不行? 当时学艺不精,把我也难住了,我只知道Base1和Base2虚拟继承Base就可以解决二义性问题,个中细节并不是很清楚,于是就在VS2013环境下研究了一下虚拟继承的模型。

    我们知道在直接继承中,先继承的放在前面,后继承的放在后面,最后才是派生类中新增的成员。在本文开始的部分,存在二义性的那个例子就是这样的。

    那么在虚拟继承中有什么规律呢?下面的规律是我测试了许多例子后得出的,如有错误还望指正。


规律一:如果一个派生类虚拟继承一个基类,那么派生类的模型如下:


技术分享

    也就是说,只要有虚拟继承,派生类最开始的部分必然是一个地址,这个地址间接指向虚拟继承自基类的部分。然后是派生类固有成员,最后是虚拟继承自基类的部分。


规律二:如果一个派生类虚拟继承了两个基类,那么派生类的模型如下:

技术分享


    如上图,无论派生类虚拟继承多少个基类,在开始的部分只有一个地址,指向所有虚拟继承自基类的开始,虚拟继承自基类的部分放在一起,先继承的放在前面,后继承的放在后面。


规律三:在多继承中,只要有虚拟继承不论有无直接继承,派生类最开始必然是一个地址,这个地址间接指向虚拟继承自基类的开始部分。


规律四:如果在多继承中既有直接继承又有虚拟继承,无论先是直接继承还是先是虚拟继承,在满足规律三的前提下,存放的顺序依次是直接继承的部分、派生类固有成员、虚拟继承基类的部分。如下图所示:

技术分享

    在上面的继承中直接继承部分,先继承的放在前面,后继承的放在后面。虚拟继承部分类似。


规律五:



    









本文出自 “牛丽” 博客,请务必保留此出处http://15129279495.blog.51cto.com/10845420/1765052

深度探索C++关键字之 virtual

标签:virtual 继承 多态 模型

原文地址:http://15129279495.blog.51cto.com/10845420/1765052

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!