这里的例子全部来自陈皓的 C++ 对象的内存布局(上),经过修改的。
编译器:g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2
环境:ubuntu 15.04 64位系统(地址占8字节)
例子1:
单一的一般继承,所有函数均是virtual,每个类中均有1个long long变量:

1 class Parent { 2 public: 3 LL iparent; 4 Parent ():iparent (10) {} 5 virtual void f() { cout << " 1 " << endl; } 6 virtual void g() { cout << " 2 " << endl; } 7 virtual void h() { cout << " 3 " << endl; } 8 9 }; 10 11 class Child : public Parent { 12 public: 13 LL ichild; 14 Child():ichild(100) {} 15 virtual void f() { cout << " 11 " << endl; } 16 virtual void g_child() { cout << " 4 " << endl; } 17 virtual void h_child() { cout << " 5 " << endl; } 18 }; 19 20 class GrandChild : public Child{ 21 public: 22 LL igrandchild; 23 GrandChild():igrandchild(1000) {} 24 virtual void f() { cout << " 111 " << endl; } 25 virtual void g_child() { cout << " 44 " << endl; } 26 virtual void h_grandchild() { cout << " 6 " << endl; } 27 }; 28 int main(void) 29 { 30 typedef void(*Fun)(void); 31 GrandChild gc; 32 33 LL** pVtab = (LL**)&gc; 34 Fun pFun=NULL; 35 36 cout << "[0] GrandChild::_vptr->" << endl; 37 for (int i=0; i<6; i++){ 38 pFun = (Fun)pVtab[0][i]; 39 cout << " ["<<i<<"] "; 40 pFun(); 41 } 42 LL *p=(LL*)&gc; 43 cout << "[1] Parent.iparent = " <<*(p+1)<< endl; 44 cout << "[2] Child.ichild = " << *(p+2)<< endl; 45 cout << "[3] GrandChild.igrandchild = " << *(p+3)<< endl; 46 47 cout<<"对象gc的大小:"<<sizeof(gc)<<endl; 48 49 return 0; 50 }
输出:
、
解释:继承关系为 Parent<--Child<--GrandChild,其中Child是中间类,覆盖了Parent中一个函数f。GrandChild是最底派生类,覆盖了Parent和Child的函数f,再覆盖Child中的函数g_child。
总结:GrandChild的对象gc一共占4*8=32个字节。其中首项是虚函数表指针,剩下的3项是3个类中的成员变量,按继承的声明顺序排列。虚函数表中有6个函数,其中来自GrandChild的有3个,Child的1个,Parent的2个。GrandChild的3个必定不会少,而且前两个函数f和g_child就覆盖掉所有基类中同名的函数。Parent中剩下2个没有被覆盖的,而f不幸被覆盖。Child中只剩下1个了,前两个都被覆盖了。
其实可以先看两层的Parent<--Child,而GrandChild先不看。那么派生类覆盖掉基类1个函数,剩下的就是2+3=5个函数。来了新的基类GrandChild后,也新来3个函数,但是其中2个已经存在,先覆盖,剩下一个直接加进去,即5+1=6个函数。
验证了如下这副图:

例子2:
三
原文:http://www.cnblogs.com/xcw0754/p/4973978.html