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

Language agnostic 虚拟或动态调度的合理底层实现是什么?,language-agnostic,virtual,Language Agnostic,Virtual,最流行的方式(或者我听说的)似乎是虚拟桌子,但是还有什么其他的选择呢 的答案提供了几个例子,比如在运行时遍历层次结构或者将对象的地址映射到一些更大的信息表,但是问题是C++的特定,尽管答案大多不是。 因此,这里有一个语言不可知(或者我希望如此)的问题: 除了vtables之外,还有哪些其他实现虚拟/动态调度的方法? 请注意,这并不是关于速度、易实现性、代码大小等之间的权衡,尽管在答案中包含这些因素会非常好。方法1:平面VTable。 类类型的所有虚拟方法(包括继承的方法)都表示在方法指针表中,每

最流行的方式(或者我听说的)似乎是虚拟桌子,但是还有什么其他的选择呢

的答案提供了几个例子,比如在运行时遍历层次结构或者将对象的地址映射到一些更大的信息表,但是问题是C++的特定,尽管答案大多不是。 因此,这里有一个语言不可知(或者我希望如此)的问题:

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

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

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

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

方法3:消息传递。编译器不生成方法指针的正式表。相反,每个虚拟方法都被分配一个唯一的id,并通过分派函数调用。分派函数可以只是方法ID上的case/switch语句。案例块可以调用对象的各个方法,也可以直接实现行为

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

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


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

我相信Python是这样工作的:函数是存储在属性表中的一级对象,就像该类拥有的任何其他成员对象一样。调用函数时,会在属性哈希表中查找并调用该函数。重写一个方法意味着简单地用另一个同名的函数对象替换函数对象。

我认为这不是真正的语言不可知论。V表对于C++、SimultExchange for SimulalTalk等来说是完美的。它确实依赖于语言。除去其他语言特定的问题,删除额外的标签与继承是如何工作有关的,如果调度规则基于一个更动态类型(SD vs MMD)。注意这与VTBLs确实是一样的。@ Belyynales,根本不是。Vtable是非常静态的,而属性列表是完全动态的。此外,查找是按名称(哈希)而不是按索引进行的。不过,在后台,vtbl和属性列表是相同的。它们最终都是间接通话。当然,属性列表可以在语言内部重新分配;但是基本概念是相同的。@BillyONeal,问题是关于实现细节,而不是概念。您是否声称数组和哈希表是完全相同的东西?