【发布时间】:2020-03-26 22:06:34
【问题描述】:
所以我知道在 c++ 中,虚拟方法是针对存储在表中的每个类,并且每个实例都有一个指向该表的指针。所以我的问题是子类表的样子。我将提供一个汇编指令:
vtable for Derived:
.long 0
.long _typeinfo for Derived
.long _Derived::set()
.globl _vtable for Base
.section .rdata$vtable for Base,"dr"
.linkonce same_size
.align 4
所以,从这里我可以看到 Derived 有一个虚拟方法,即set(),但让我烦恼的部分是 Base 的 vtable。 Derived vptr 是否持有指向 Base vptr 的指针,或者它是否存储在 Derived 的 vtable 中。
我注意到在代码编译器中只将 vtable 存储在对象的 0 地址,一次在 Base 构造函数中,一次在 Derived 中。为什么 vtable 没有被覆盖?
附:我不太懂指令
编辑:
class Base{
virtual void print() {
printf("Base");
}
}
class Derived : Base{
virtual void print(){
printf("Derived");
}
}
【问题讨论】:
-
也许它被覆盖了。但是,如果先存储基本存储,然后再存储派生,则它会被正确的值覆盖。
-
@ErikEidt 至少在 g++ 代码中,构造函数将 vtable 指针写入对象。所以基础构造函数将基础 vtable 写入对象,然后派生构造函数用派生 vtable 覆盖它。
-
我对指令了解不多,但我认为
.globl只是符号可见性的问题;vtable for Derived仅在存储信息方面首先由树构成.long。 -
他问的问题对我来说很清楚:“编译器只是将 vtable 存储在对象的 0 地址,一次在 Base 构造函数中,一次在 Derived 中。为什么不覆盖 vtable?” 。他已经看到两个构造函数都写入同一个位置。我解释了它是如何工作的。
-
@Jester 是的,你明白我的要求,抱歉问题的格式不好。谢谢你的澄清。
标签: c++ assembly polymorphism vtable