关于虚拟继承的思考

原创 2004年06月23日 18:52:00
虚拟继承在一般的应用中很少用到,所以也往往被忽视,这也主要是因为在C++中,多重继承是不推荐的,而一旦离开了多重继承,虚拟继承就完全失去了存在的必要(因为这样只会降低效率和占用更多的空间,实在是一无是处)。
以下面的一个例子为例:
#include <iostream.h>
#include <memory.h>

class
 CA
{

    int
 k; //为了便于说明后面的内存结构特别添加
public:
    void
 f() {cout << "CA::f" << endl;}
};


class
 CB :  public CA
{
};


class
 CC :  public CA
{
};


class
 CD : public CB, public CC
{
};


void
 main()
{

    CD d;
    d.f();
}

当编译上述代码时,我们会收到如下的错误提示:
error C2385: 'CD::f' is ambiguous
即编译器无法确定你在d.f()中要调用的函数f到底是哪一个。这里可能会让人觉得有些奇怪,命名只定义了一个CA::f,既然大家都派生自CA,那自然就是调用的CA::f,为什么还无法确定呢?
这是因为编译器在进行编译的时候,需要确定子类的函数定义,如CA::f是确定的,那么在编译CB、CC时还需要在编译器的语法树中生成CB::f,CC::f等标识,那么,在编译CD的时候,由于CB、CC都有一个函数f,此时,编译器将试图生成两个CD::f标识,显然这时就要报错了。(当我们不使用CD::f的时候,以上标识都不会生成,所以,如果去掉d.f()一句,程序将顺利通过编译)

要解决这个问题,有两个方法:
1
、重载函数f():此时由于我们明确定义了CD::f,编译器检查到CD::f()调用时就无需再像上面一样去逐级生成CD::f标识了;
此时CD的元素结构如下:
--------
|
CB(CA)|
|
CC(CA)|
--------

故此时的sizeof(CD) = 8;(CB、CC各有一个元素k)
2
、使用虚拟继承:虚拟继承又称作共享继承,这种共享其实也是编译期间实现的,当使用虚拟继承时,上面的程序将变成下面的形式:
#include <iostream.h>
#include <memory.h>

class
 CA
{

    int
 k;
public
:
    void
 f() {cout << "CA::f" << endl;}
};


class
 CB :  virtual public CA
{
};


class
 CC :  virtual public CA
{
};


class
 CD : public CB, public CC
{
};


void
 main()
{

    CD d;
    d.f();
}

此时,当编译器确定d.f()调用的具体含义时,将生成如下的CD结构:
----
|
CB|
|
CC|
|
CA|
----

同时,在CB、CC中都分别包含了一个指向CA的vbptr(virtual base table pointer),其中记录的是从CB、CC的元素到CA的元素之间的偏移量。此时,不会生成各子类的函数f标识,除非子类重载了该函数,从而达到“共享”的目的。
也正因此,此时的sizeof(CD) = 12(两个vbptr + sizoef(int);
所有这一切都是编译期间决定的,只是编译器为了提供这样一个新的语法功能为我们多作了一些事情而已。

注:以上讨论限MS Visual C++编译器。

关于虚拟继承的思考

转载说明:http://blog.csdn.net/billdavid/article/details/24317 虚拟继承在一般的应用中很少用到,所以也往往被忽视,这也主要是因为在C++中...
  • Niteip
  • Niteip
  • 2013年12月17日 11:16
  • 706

【逻辑思考】除夕博思

年30晚上春晚开始之前,本想写点什么,但是由于窗外炮竹响个不停(由于住的是一楼,楼与楼之间的空隔特别小,鞭炮就在窗下响,离的太近),所以根本没办法整理思路,想到这首诗。我本将心写博客,奈何炮竹响不停。...
  • testcs_dn
  • testcs_dn
  • 2017年02月03日 08:54
  • 570

关于栈的小思考

1.栈有时候就像个顺序表,只不过用个top,亦或是top和base来进行模拟,多了个指向而已...
  • xbh16110501060
  • xbh16110501060
  • 2017年01月31日 22:37
  • 137

关于 衰老的思考

从事生命科学工作已经有一段时间,今天跟大家分享一下我对衰老的思考。 (一).我认为衰老是这样形成的    在体外进行细胞传代培养,研究人员发现细胞的代数越多,细胞的分裂会变慢。    我...
  • weizhongxing6
  • weizhongxing6
  • 2016年02月18日 10:24
  • 547

读《面向对象的思考过程》作者matt Weisfeld

最近接触了很多java代码,开始于机缘巧合,读了《java编程思想》的大概前四分之一,这比我读《C++primer》还要多了,两本都是大部头,我能完整读完还需毅力。惊讶于两门语言语法非常的相似,之前对...
  • czl389
  • czl389
  • 2017年02月22日 11:36
  • 1095

叔本华系列之(一)论独立的思考

即使是藏书最为丰富的图书馆,如果里面的书籍胡乱摆放,那么它的实际用处还不如一个收藏不多、但却整理得井井有条的小图书室。同样道理,如果大量的知识没有经过自己细心地思考加工,那么它的价值也远远逊色于数量较...
  • c_trekman
  • c_trekman
  • 2016年11月26日 14:55
  • 222

听罗辑思维关于商业模式的思考

互联网
  • huaishu
  • huaishu
  • 2017年07月04日 12:46
  • 181

关于语言的思考

之前写了那么多 Haskell 的不好的地方,却没有提到它好的地方,其实我必须承认我从 Haskell 身上学到了非常重要的东西,那就是对于“类型”的思考。虽然 Haskell 的类型系统有过于强烈的...
  • cytzrs
  • cytzrs
  • 2015年12月16日 13:29
  • 250

VR时代的思考

滴滴,利用手机的LBS,通讯连接,对接优化了出行需求和闲置的汽车资源。 诚然的,任何一个占据用户时间的硬件产品上,都可以开发出消磨时间的软件,游戏,新闻等。但是滴滴利用的是手机的LBS和通讯...
  • ritterliu
  • ritterliu
  • 2016年07月04日 22:49
  • 1505

关于项目管理的一些思考

好记忆不如烂笔头 ,   所以还是要记录下来的。 关于项目管理,作如下的简要描述,可以给自己一个明确的提示。 前期 项目前期是一个项目很关键的时候,么有一个好的开始,一切都会很糟。 所以前期的准备工...
  • supingemail
  • supingemail
  • 2016年06月01日 01:42
  • 281
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于虚拟继承的思考
举报原因:
原因补充:

(最多只允许输入30个字)