想问问‘虚拟继承’怎么用?用来做什么?

wfowler 2004-10-15 08:32:52
谢谢您有兴趣回答这个基本的问题。
...全文
276 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
cxd6287175 2010-06-22
  • 打赏
  • 举报
回复
学习学习就
sharkhuang 2004-10-15
  • 打赏
  • 举报
回复
防止恐怖菱型
umbrella1984 2004-10-15
  • 打赏
  • 举报
回复
class A : virtral public B

虚拟继承,当某个类继承A的时候也继承了B的话这个类就不知道是调用A里的B方法还是自身继承的B方法,这样就造成了二义性,所以这里的virtual保证B只有一个,丢掉其他多余的。


在类重载中我们一般使用以下的方式:

class Base
{
void Echo() { printf("Echo from Base");}
};

class Middle : public Base {}

class Child : public Middle {}

可以很清楚的看出重载过程是 Base->Middle->Child.
这样的结构使用默认的重载方式就可以了.

void main()
{
Child c;
c.Echo(); // 正确.
}

但是在某些时候,我们需要从基类分出若干子类,然后再由子类进行多重继承,
这个时候以上的方法就会出错.

比如:

class Base
{
void Echo() { printf("Echo from Base");}
};

class Middle1 : public Base {}
class Middle2 : public Base {}

class Child : public Middle1,Middle2 {}

void main()
{
Child c;
c.Echo(); // 错误.函数调用不明确.
}

这是因为编译时系统认为Middle1和Middle2是两个类体系
来自不同的Base类(虽然两个Base声明一模一样),所以在调用
Base类的Echo时无法确认指向那一个.

解决的方法是使用"虚拟继承".

如下所示:

class Base
{
void Echo() { printf("Echo from Base");}
};

class Middle1 : virtual public Base {}
class Middle2 : virtual public Base {}

class Child : public Middle1,Middle2 {}

void main()
{
Child c;
c.Echo(); // 正确.函数调用来自同一基类.
}

以下图示更能描述默认继承和虚拟继承的区别.

默认继承:

base base
| |
| |
Mid1 Mid2
| |
|
Child

存在两个类体系是出错的原因.

虚拟继承:

base
|
| |
Mid1 Mid2
| |
|
Child

使用虚拟继承将类的体系整合起来.
lamputa_lito 2004-10-15
  • 打赏
  • 举报
回复
bllue215() 的回答是正确的。对于虚拟继承的理解,可以用共享概念来理解。
对于如下的继承关系。class a{ public: int i;}; class b:public a{}; class c:public a{}; class d:public b,public c{};上述的继承体系中,由于类b和类c都是一般的继承于a,所以在b、c两个类对象中,都会有其基类a的数据i的一份拷贝。也就是int b::i和 int c::i,而此时类d继承于b和c,所以,类d中就会有两份i的数据,一份继承与b而来,另一份继承于c而来,所以对于d来说,这是冗余的,如果类b和c都是virtual public a的话,那么在类d中,就只有一份数据。而且无论以后怎么继承,a都只有一份。
其实虚拟继承的实现因编译器不同而不同,基本上都是用virtual base指针来实现的,只是这个指针的位置放在哪个地方而异。
我个人对这整个过程的了解还是比较模糊的,希望有高手能给我解析一下虚拟继承的实现概要,不胜感激!!
doolin 2004-10-15
  • 打赏
  • 举报
回复
虚拟继承一般用在多重继承中.在多重继承中由于某个基类可能在类层次结构中出现多次,非虚拟继承的话,派生类中将含有几个基类的成员拷贝,这样产生冗余.最常见的就是iostream类.
通过虚拟继承的派生类只无论基类在类层次结构中出现几次就,都只有一份拷贝,避免了上述情况发生.
用法: class driver : virtual public base
用来: 如上所述
Squall1009 2004-10-15
  • 打赏
  • 举报
回复
比如一个类d继承于两个类b和c,但他的两个b和c有相同的参数或者方法
所以这个时候最好就是把他的两个b和c的相同的参数和方法放到一个类a中
在让b和c虚拟继承于a,然后d再继承b和c.这样就没有二义性了.
renheihei 2004-10-15
  • 打赏
  • 举报
回复
mark
greenteanet 2004-10-15
  • 打赏
  • 举报
回复
为了避免二义性,例子上面已经说过
nwpulipeng 2004-10-15
  • 打赏
  • 举报
回复
学习中.
帮顶混分

64,691

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧