繁体   English   中英

虚函数的 Vtable 是如何工作的

[英]How Vtable of Virtual functions work

我对虚拟表有一个小疑问,每当编译器遇到 class 中的虚拟函数时,它都会创建 Vtable 并将虚拟函数地址放在那里。 对于继承的其他 class,情况类似。 它是否在每个指向每个 Vtable 的 class 中创建一个新指针? 如果不是,当创建派生 class 的新实例并将其分配给 Base PTR 时,它如何访问虚拟 function?

每次创建包含虚函数的 class,或者从包含虚函数的 class 派生时,编译器都会为该 class 创建一个唯一的 VTABLE。

如果不覆盖在基类 class 中声明为虚拟的 function,编译器将使用派生的 class 中基类版本的地址。

然后它将VPTR放入class。当使用简单的inheritance时,每个object只有一个VPTR。必须初始化VPTR以指向适当的VTABLE的起始地址。 (这发生在构造函数中。)一旦 VPTR 被初始化为正确的 VTABLE,object 实际上“知道”它是什么类型。 但是,除非在调用虚拟 function 时使用它,否则这种自知是毫无价值的。 当您通过基地址 class 调用虚拟 function 时(编译器没有执行早期绑定所需的所有信息的情况),会发生一些特殊情况。 编译器生成不同的代码来执行 function 调用,而不是执行典型的 function 调用(它只是对特定地址的汇编语言 CALL)。

对于每个具有虚函数的 class,都会创建一个 vtable。 然后,当使用构造函数创建 class 的 object 时,构造函数将适当的 vtable 复制到 object。因此每个 object 都有一个指向其 vtable 的指针(或者在多个 inheritance 的情况下,必要时,Orr到它的每个 vtables。)。 编译器知道vtable在object中的什么位置,所以当需要调用虚方法时,它输出字节码来阻止vtable,查找合适的方法,然后跳转到它的地址。

在单个 inheritance 的简单情况下,子 class 从父类的 vtable 的副本开始,然后为子 class 中覆盖父类方法的每个虚拟方法获取一个覆盖条目。 (并且它还为子 clad 中的每个虚拟 function 获取一个新条目,该条目不会覆盖父 class 方法)

每当程序编译时,都会为每个 class 创建虚拟表,这清楚地表明了每个 class 基础创建 vtables 的事实。 在运行时,当创建 object 时,编译器将 vptr 分配给 object,它指向特定类 object 的虚拟表。简而言之,vptr 是根据 object 创建的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM