在上一篇文章中讨论了C++单一一般继承的对象内存布局http://www.cnblogs.com/uangyy/p/4621561.html
接下来继续讨论第二种情况:
2.单一的虚拟继承:有成员变量,有虚函数和虚函数的覆盖,虚拟继承。
我们假设下面这样一种继承关系
源码如下:
#include <iostream> using namespace std; class Parent { public: int iparent; Parent() : iparent(10) {} virtual void f() { cout << "Parent::f()" << endl; } virtual void g() { cout << "Parent::g()" << endl; } }; class Child : virtual public Parent { public: int ichild; Child() : ichild(100) {} virtual void f() { cout << "Child::f()" << endl; } virtual void g_child() { cout << "Child::g_child()" << endl; } }; int main(int argc, char **argv) { Child c; typedef void(*Fun)(void); Fun pf; cout << "[0] Child::vfptr->" << endl; cout << " [0] "; pf = (Fun)*((int *)*(int *)&c + 0); pf(); cout << " [0] 0x" << (Fun)*((int *)*(int *)&c + 1) << endl; cout << "[1] Child::vbptr->" << endl; cout << " [0] " << *((int *)*((int *)&c + 1) + 0) << endl; cout << " [1] " << *((int *)*((int *)&c + 1) + 1) << endl; cout << " [2] " << *((int *)*((int *)&c + 1) + 2) << endl; cout << "[2] Child.ichild = " << (int)*((int *)&c + 2) << endl; cout << "[3] = 0x" << (int *)*((int *)&c + 3) << endl; cout << "[4] Parent::vfptr->" << endl; cout << " [0] "; pf = (Fun)*((int *)*((int *)&c + 4) + 0); pf(); cout << " [1] "; pf = (Fun)*((int *)*((int *)&c + 4) + 1); pf(); cout << " [2] 0x" << (Fun)*((int *)*((int *)&c +4) + 2) << endl; cout << "[5] Parent.iparent = " << (int)*((int *)&c + 5) << endl; return 0; }
代码运行结果如下:
[0] Child::vfptr-> [0] Child::g_child() [0] 0x00000000 [1] Child::vbptr-> [0] -4 [1] 12 [2] 0 [2] Child.ichild = 100 [3] = 0x00000000 [4] Parent::vfptr-> [0] Child::f() [1] Parent::g() [2] 0x00000000 [5] Parent.iparent = 10
下面是该对象的内存布局图:
由上图我们可以知道:
1.在虚拟继承关系下,派生类的对象会产生一个名为虚基类表指针的指针vbptr,里面存放的是基类在对象中的偏移地址(从1开始,0单元存放的不知道有什么用)
2.在这种关系先,被继承的基类放在最后面,首先放的是派生类的成员变量和虚函数表
3.存放的顺序为:派生类虚函数表指针 -> 虚基类表指针 -> 派生类的成员变量 -> NULL -> 基类虚函数表指针 -> 基类成员变量
sizeof(c) = 24 : 2 * sizeof(vfptr) + 2 * sizeof(int) + sizeof(vbptr) + sizeof(void *)
注意:1.在虚拟机城的继承关系下,派生类的对象会有一个虚基类表指针,占用4个字节;
2.在派生类和被虚拟继承的基类之间有一个空指针。