这很简单... vftable本身是one-per-class
,指针是one-per-instance
。两个相同类型的实例的vftable指针指向同一个位置。
class A
{
virtual void foo();
virtual void goo();
}
class B : public A
{
virtual void foo();
}
在内存中,你将有:
vftable for A:
+----------+---------+
| 0x01 | 0x02 |
+----------+---------+
&A::foo() &A::goo()
vftable for B:
+----------+---------+
| 0x11 | 0x12 |
+----------+---------+
&B::foo() &A::goo()
假设您创建两个对象:
A a;
B b;
A的第一个成员是:
vftableptr: 0x01
B的第一个成员将是
vftableptr: 0x11
一般而言,已实现多态得到vftable
的地址,添加函数偏移(例如,如果我们称之为goo()
,偏移量是1),和跳跃到该位置。由于对象类型不同,它们将指向不同的位置,但vftables(不同)可以包含类似的成员。
重要提示:值是假的,偏移量不是1
也不是地址0x01
等,我选择他们来说明问题。
评论,如果你从一个类层次结构有有一个类的单个实例是没有问题的。我想知道的是,如果为上述代码执行两次“new B”,则会在内存中分别存储“foo()”的副本,但只有一个vtable.virtual指针指向vtable的条目(每个类只有一个)..那么如何解决单独实例的虚函数调用? – ustulation
+1对于一个很好的解释。 @ustulation:在此背景下展开您的问题。B的所有实例都有一个指向位置'0x11'的vtable,但是B的每个函数标识B的不同实例的方式是从所有成员函数的第一个“不可见”参数开始的,它是实例本身的指针,我们在函数中将this引用为this,或者在不使用this的情况下引用成员变量或函数时隐式推断。 –
oh..ok ..所以基本上我的理解,会有多个副本“foo()”不正确..因为马克B似乎也说...“foo()”总是在相同的地方,但其中的操作(关于成员变量,传递参数或局部变量)将获得不同的副本,并将由“this”指针解决...我是否关闭? – ustulation