因此,我知道在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()
,但是困扰我的部分是vtable for Base。派生vptr是持有指向基本vptr的指针还是存储在派生vtable中。我注意到在代码编译器中,vtable仅将vtable存储在对象的0地址处,一次存储在Base构造函数中,一次存储在Derived中。为什么vtable不被覆盖?
P.S。我不太了解指令
编辑:
class Base{
virtual void print() {
printf("Base");
}
}
class Derived : Base{
virtual void print(){
printf("Derived");
}
}
简单的答案是:它取决于编译器。该标准未指定应如何实施,而仅规定其行为。
在实践中,实现倾向于简单地具有一个与基本vtable相同的结构开头的派生vtable,而不是在末尾附加派生类方法(也就是说,派生类中有新方法,而不是覆盖)。
vtable指针仅指向整体表的开头。如果通过基指针类型访问该对象,则没有人可以超越基类方法的末尾。
如果指针是派生类型的,则相同的指针将在表的下方继续访问派生类中声明的虚拟方法。