什么是虚拟或动态调度的合理底层实现?

时间:2011-11-24 05:13:18

标签: language-agnostic virtual

最流行的方式(或者我听说过)似乎是一个虚拟的桌子,但还有其他替代方案吗?

This question的答案提供了一些示例,例如在运行时遍历层次结构或将对象的地址映射到更大的信息表,但问题是C ++特定的,尽管答案通常不是。

所以,这是一个与语言无关(或者我希望如此)的问题:

除了vtables之外,还有哪些其他实现虚拟/动态调度的方法?

请注意,这是关于速度,易于实现,代码大小等之间的权衡,尽管这些在答案中会非常好。

2 个答案:

答案 0 :(得分:8)

方法1:平坦的VTable。 类类型的所有虚方法(包括继承方法)都在方法指针表中表示,每个虚方法一个。调用需要通过方法指针在表中的固定偏移量处调用间接。每个新类创建自己的vtable,复制其祖先的vtable,用指向新方法的指针覆盖在类中重写的虚拟方法的指针,并添加在表末尾的类中定义的新虚拟方法。

方法2:链接的VTable(又名动态方法表) 只有在类类型中声明或覆盖的虚方法才会占用链接的vtable中的空间。为每个方法分配一个id,id和方法指针一起存储在动态方法表中。调用需要扫描动态方法表,以查找虚拟方法ID的匹配项。如果未找到匹配项,则扫描将继续执行类的直接祖先的动态方法表,依此类推,直到找到匹配项或者您的祖先用完为止。

方法3:消息传递。编译器不生成正式的方法指针表。而是为每个虚拟方法分配一个唯一的id,并通过调度函数调用。 dispatch函数可以简单地是方法id上的case / switch语句。大小写块可以调用对象的各个方法,也可以直接实现行为。

动态方法表实际上是传统vtable和消息传递的混合体。纯消息传递通常很少或不期望参数对于调用是什么。 Windows WndProc是消息传递的一个示例,替换窗口句柄的wndproc指针是挂钩或覆盖默认行为的方法。 WndProc有一个固定的参数结构,所有消息都必须在其中找到附加其特定参数数据的方法。

消息传递的强度是灵活性,但通常是性能成本。 VTable虚拟方法的发送速度非常快(只是间接调用),但一旦建立就非常不灵活。由于每个类VTable都包含所有继承虚拟方法的插槽,因此VTable需要比动态方法表更多的内存,尤其是在深层对象层次结构中。

在Delphi编程语言中,虚拟方法使用VTable实现,动态方法使用动态方法表实现,WndProcs使用消息传递。

答案 1 :(得分:0)

我相信Python的工作原理如下:函数是存储在属性表中的第一类对象,就像该类拥有的任何其他成员对象一样。调用函数时,将在属性哈希表中查找该函数并调用该函数。覆盖方法意味着简单地用另一个具有相同名称的函数对象替换函数对象。