V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
hxndg
V2EX  ›  问与答

到底 C++多继承里几个虚表?

  •  
  •   hxndg · 2016-05-20 00:14:00 +08:00 · 5628 次点击
    这是一个创建于 3114 天前的主题,其中的信息可能已经有所发展或是发生改变。

    跟同学聊天的时候,说是一个类的对象只有一个虚表。可是多继承的是什么情况?比方说 c 继承 a 和 b 。 a , b 都有自己的虚表。那么 c 虚表到底是怎么维持的?书里说的是维持多个虚表,现在有变化么?

    第 1 条附言  ·  2016-05-20 01:30:35 +08:00

    还有这样一个问题,以上图为例,就是说比方说我可以将一个Base1的指针(姑且叫做bp_1)指向派生类,但是很明显的,这个指针并不能调用另一个基类也就是Base2里的mumable函数。但是这个图里完全体现不出来这一点阿?

    14 条回复    2016-05-20 15:52:32 +08:00
    introom
        1
    introom  
       2016-05-20 00:28:55 +08:00 via Android   ❤️ 1
    一个类对应一个 vtbl, 如果有虚函数的话。
    所以 c 这个实例有三个 vptr, 分别指向 vtbl{a,b,c}
    hxndg
        2
    hxndg  
    OP
       2016-05-20 00:29:26 +08:00
    倘若 c 又定义了一个虚函数,那么这个虚函数会扔到哪里呢?
    hxndg
        3
    hxndg  
    OP
       2016-05-20 00:30:12 +08:00
    @introom 也就是说如果 c 又定义了一个虚函数,那么又多一个虚表了?
    sfqtsh
        4
    sfqtsh  
       2016-05-20 02:03:31 +08:00 via Android   ❤️ 1
    c 对象有两个虚函数表指针,指向两个虚函数表。 c 中覆盖的虚函数会替换掉两个表中同名的虚函数指针位置。若是普通多重继承,根据继承顺序, c 中多余的虚函数的地址会附加到第一个虚函数表指针指向的虚函数表的后面。
    若是还有虚继承,根据不同的编译器实现,比如,微软家的,对象还会存在一个虚基表指针,指向一个虚基表,里面存有虚基类对象的偏移。

    微软编译器有一个隐含的编译选项-d1reportSingleClassLayout 类名,可以很方便地查看对象内存分布,你可以以此学习。
    hxndg
        5
    hxndg  
    OP
       2016-05-20 02:33:46 +08:00
    @sfqtsh 这个多余的虚函数指的是什么?是指 c 里新定义,还是 c 通过继承 b 的来的 mumble ,也就是在图片里 Base1 subobject 的虚函数表里包含着 Base2 mumble 是这个多余的虚函数么?虚表的个数能否总结为上一层带有虚函数的类个数-1 呢?
    sfqtsh
        6
    sfqtsh  
       2016-05-20 02:53:27 +08:00 via Android   ❤️ 1
    @hxndg
    1.指新定义的
    2.不能。
    lsmgeb89
        7
    lsmgeb89  
       2016-05-20 05:20:17 +08:00   ❤️ 1
    实在弄不清楚,就写个代码看。

    编译器有一些选项可以打印这些信息的,记得 VS 的 cl 和 g++ 都有。
    visionsmile
        8
    visionsmile  
       2016-05-20 06:31:00 +08:00 via Android   ❤️ 1
    有的编译器会把多个虚表合并成一个,有的是具有多个虚表。一个和多个都没什么妨碍,函数位置都能通过 offset 算出来的。
    hxndg
        9
    hxndg  
    OP
       2016-05-20 10:12:34 +08:00 via Android
    @lsmgeb89 我能问问 g++是什么选项不?我搜了,没找到~………
    hxndg
        10
    hxndg  
    OP
       2016-05-20 10:52:12 +08:00
    @visionsmile
    @lsmgeb89
    @sfqtsh
    @introom
    去 google 上搜了一下,然后搜到了,尴尬。。。。表示这个有点炯,感谢诸位。
    zuoxiaomo
        11
    zuoxiaomo  
       2016-05-20 11:20:08 +08:00
    c++ primer 里边有一章介绍虚函数表的
    visionsmile
        12
    visionsmile  
       2016-05-20 11:40:50 +08:00 via Android   ❤️ 1
    @hxndg 在多重继承下,一个 derived class 内含 n-1 个额外的 virtual tables , n 表示其上一层 base classes 的个数;针对每一个 virtual tables, derived 对象中有对应的 vptr.——深度探索 C++对象模型 P164
    visionsmile
        13
    visionsmile  
       2016-05-20 11:43:24 +08:00 via Android   ❤️ 1
    @hxndg Sun 编译器将多个 virtual tables 连锁为一个;指向次要表格的指针可由主要表格名称加上一个 offset 获得,这样的策略下每个 class 只有一个具名的 virtual table.—— P165
    hxndg
        14
    hxndg  
    OP
       2016-05-20 15:52:32 +08:00
    @visionsmile 首先很感激哈,我看到这里了。图 4.2 本身讲的也很清楚,但是具体编译器实现到底是怎么样的是我很好奇的,而且我很奇特的是为什么第一个虚表里面包含了第二个基类的虚函数。这些我没有搞明白所以提问的哈。坦白说我对于书中的一部分细节保持怀疑态度因为觉得还是不是很明白,可能我还是看的不认真把。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1134 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:51 · PVG 02:51 · LAX 10:51 · JFK 13:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.