继承关系图
class A
{
virtual aa(){};
};
class B : public virtual A
{
char j[3];//加入一个变量是为了看清楚class中的vfptr放在什么位置
public:
virtual bb(){};
};
class C : public B
{
char i[3];
public:
virtual cc(){};
};
#include <iostream>
using namespace std;
int main()
{
A aa;
int a = sizeof(aa);
B bb;
int b = sizeof(bb);
C cc;
int c = sizeof(cc);
printf("a= %d\nb=%d\nc=%d\n",a,b,c);
return 0;
}
下面是内存图
集体的单步调试内存图如下
图一 单层虚继承刚到aa时的图
图二 单层继承aa运行完之后的图
从图一可以看出,变量在内存的位置都定下来了(例如bb.j、cc.i、cc.B.j,还有与类无关的a、b、c三个变量),与虚函数有关的aa._vfptr、bb._vfptr等的内存值还是空的(0xcccccccc)然后到了图二就可以看出aa._vfptr的值就确定了,这说明虚函数表指针(vptr)在运行时才确定真正的值。
图三 单层虚继承刚到bb时的图
图四 单层继承bb运行完之后的图
图三与图四的比较可以看出,虚函数指针_vfptr或者vptr在运行时才确定,同样指向virtual base class的类的偏移或者指针也是在运行时确定。
图五 单层虚继承刚到aa时的图
图六 单层继承aa运行完之后的图
图七 虚函数表
虚函数表在程序代码之后,中间以四个字节的0隔开。