多重继承的多态性在汇编中如何工作?

问题描述 投票:0回答:1

所以我相信我理解单继承的多态性,假设你有类 Dog 和 Cat 从 Animal 接口继承,并且 Animal 有一个 Speak 和 Walk 函数,所以你为 Dog 和 Cat 生成 v 表,它们都有一个指向它们的函数指针各自的 Speak 和 Walk 函数,如果我为一般 Animal 调用其中一个通用函数,程序集将获取 Animal 的第一个数据成员(它是指向 v 表的指针),取消引用它,然后添加正确的偏移量获得正确的函数指针,然后在内存地址调用该函数。

所以我的问题是这对于多重继承如何工作。因此,对于这个例子,我将从接口 Animal 和 Colorable 继承 Dog 和 Cat:Animal 将具有 Speak 和 Walk 函数,Colorable 将具有 GetColor 和 SetColor 函数。 Dog 是否有一个针对 Animal 函数的 v 表,然后有一个针对 Colorable 函数的 v 表?这是否意味着每个 Colorable 类都会有内存填充,这样它的 v 表就是第二个成员,以便您可以使用 Colorable 进行多态性?或者您是否有一个指向 v 表指针表的三重指针,以便您只有内存填充的类实例而不是对象实例?取消引用三重指针会不会很慢?

还有其他我没有考虑的记忆模式吗?我还没有找到很多这方面的好资源。

我知道C#、Java、Rust等都支持多态性和多重继承,所以我觉得这是一个解决的事情。

我尝试过在 YouTube、Stack Overflow 和 Google 上进行搜索,但都没有给我带来好的结果。我确实找到了一个关于 Java 进行多重继承的页面,但对我来说它有点神秘且难以理解。

编辑: 为了补充说明,我正在专门寻找单层继承,例如 Rust 的特征语法。关于 C# 和 Java 多重继承,我指的是为一个对象使用多个接口并能够使用所述接口作为静态多态性的类型的能力。 Rust 允许实现多个特征。

assembly polymorphism multiple-inheritance vtable static-polymorphism
1个回答
0
投票

您所说的所有语言都没有按照您描述的方式实现继承。您正在描述 C++ - 在 C++ 中,您在类的开头有一个指向 vtable 的指针。

在 C++ 中,第一个基类与派生类合并:Dog 开头的 vtable 指针也是内切 Animal 基类的 vtable 指针(如果 Animal 是第一个)。 vtable 将从 Animal 虚拟函数 (

Speak
,
Walk
) 开始,然后是其他基类函数 (
GetColor
,
SetColor
),然后是 Dog 的其他虚拟函数(如果有的话)。

所有其他基类将有不同的 vtable。这意味着刻入的 Colorable vtable 指针将指向 Dog 的一个 different vtable - 第一个具有

GetColor
SetColor
的 vtable。而且,这些虚函数将与主虚函数表中的虚函数“不一样”!它们将是一个特殊的版本,首先纠正指针(指向 Dog 实例,而不是刻录的 Colorable 实例)。 在 Java 中,每个基本接口都有一个 vtable,运行时会在接口列表中进行搜索以找到正确的接口。它在 C# 中几乎相同,只有细微的差别。

在 Rust 中,“类”内根本没有指向 vtable 的指针。相反,Rust 对接口本身使用“胖指针”——对接口的引用是双倍大小的,因为它们包含两个指针:一个用于对象,一个用于 vtable。仅当您将对象转换为

&dyn Interface

类型时才会生成指向 vtable 的指针,而不是之前。指针指向vtable内的正确位置,因此当前的接口函数将首先出现:


    &dyn Animal
  • 将等于
    {&Dog, &Dog_vtable + 0}
    ,
  • &dyn Colorable
  • 将等于
    {&Dog, &Dog_vtable + 16}
    ,等等
    
        
© www.soinside.com 2019 - 2024. All rights reserved.