单继承的虚函数类 虚表的一些讨论

一般的书上都说,虚函数是在运行时根据对象的实际类型“动态决定”函数入口。但什么是“动态决定”呢?实际上C++编译器在实现这个功能的时候,并非真的 等到虚函数被调用时才去判断这个对象是什么类型的。下面我用一个简单的图表来说明C++编译器到底干了些什么。假设有两个类

struct Base {
  virtual void f();
  virtual void g();
};

struct Derived : public Base {
  virtual void f();
  virtual void g();
};

Base 和 Derived 各有一个虚表,分别是 VTable_B 和 VTable_D ,那么编译器是怎么通过只用一个虚表指针来实现下面的“动态”调用呢?

Base *pB = new Derived();
pB->f();

先让我们看Base和Derived对象是怎么存储的,以及两个类的虚表结构

Base:                    VTable_B:
------------         -------------
|  vptr       |        |  f() 入口    |
+---------+        +----------+
|  Base的   |        |  g() 入口   | 
|    数据     |        -------------
------------

Derived:                VTable_D:
------------        --------------
|  vptr       |        | f() 入口     |
+---------+        +----------+
|  Base的   |        | g() 入口    |
|    数据     |        -------------
+---------+
| Derived的|
|    数据     |
------------

pB 指针既可以指向 Base 对象,也可以指向 Derived 对象,所以 pB 本身是不确定的。但是,任何对象本身却从被 new 出来开始就是确定的, 所以 Base 对象在构造时,编译器会往 vptr 中填上 VTable_B 的地址,而 Derived 对象在构造时,编译器会往 vptr 中填上 VTable_D 的地址

等到虚函数被调用的时候,也就是 pB->f() 这行语句被执行的时候, 编译器并不需要知道 pB 到底是指向 Base 还是 Derived ,它只要直接用 vptr 就能找到正确的虚表和虚函数入口了,父类和子类的虚表结构是相似的,同一个虚函数入口在父表和子表的偏移量都是一样的

通过上面这些介绍,我想你应该能理解,为什么在单一继承的条件下,不管有多少层继承,每个对象只需一个 vptr 就行了。

多重继承的条件下,一个 vptr 行不行呢?

不行。 多重继承的时候,虚函数既有来自父类1的,也有来自父类2的,所以这些虚函数入口是不能放在同一个虚表当中的 。假设 Derived 除了 Base外,还继承 Base2,并且 Base2 中有两个虚函数 x() 和 y (),那么 Derived 对象的存储结构也许是这样的(只是大概,和具体编译器相关)。

Derived:                VTable_D:
------------        --------------
|  vptr       |        | f() 入口     |
+---------+        +----------+
|  Base的   |        | g() 入口    |
|    数据     |        -------------
+---------+
| vptr2      |          VTable_D2:
+---------+        -------------
| Base2的  |        |  x() 入口    | 
|    数据     |        +-----------+
+---------+        | y() 入口     |
| Derived的|        -------------
|    数据     |

------------

http://www.cnblogs.com/kanego/articles/2390238.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值