C++对象模型目录
C++ - 对象模型之 内存布局
class的static member不属于任何类对象,它保存在数据段,下面我们将对nonestatic member进行分析。
基本内存布局
空类
空类 | #include <stdio.h> class Child{ };
int main(){ Child child1; Child child2; printf("child1 : address(0x%p) size(%d)\n", &child1,sizeof(child1)); printf("child2 : address(0x%p) size(%d)\n", &child2,sizeof(child2)); printf("child1.char : 0x%02x\n",child1); printf("child2.char : 0x%02x\n",child2); } | ||
| |||
X86 VC++ | X86 g++ | ||
打印结果 | child1 : address(0x0012FF63) size(1) child2 : address(0x0012FF57) size(1) child1.char : 0xcc child2.char : 0xcc | 打印结果 |
|
内存布局 | Child Size: 1B |char| | 内存布局 |
|
Vtbl |
| Vtbl |
|
其他 |
| 其他 |
|
无继承
无继承 | #include <stdio.h> class Child{ public: int age; }; int main(){ Child child1; printf("child1 : address(0x%p) size(%d)\n", &child1,sizeof(child1)); printf("child1.age : address(0x%p)\n", &child1.age); } | ||
| |||
X86 VC++ | X86 g++ | ||
打印结果 | child1 : address(0x0012FF60) size(4) child1.age : address(0x0012FF60) | 打印结果 |
|
内存布局 | Child Size:4B |age| | 内存布局 |
|
Vtbl |
| Vtbl |
|
其他 |
| 其他 |
|
无继承&多态
无继承&多态 | #include <stdio.h> typedef void(*Fun)(void);
class Child{ public: int age; Child():age(8){} virtual void who(){ printf("I am child\n");} virtual void study(){ printf("study...\n");} };
int main(){ Child child; Fun fun = NULL; int * vtbl = (int *)(*((int*)&child));
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] is vptr, points to vtbl 0x%p\n",vtbl); printf("child[1] is Age : %d\n", ((int *)(&child))[1]);
for (int i=0; (Fun)vtbl[i]!=NULL;i++){ fun = (Fun)vtbl[i]; printf("vtbl[%d] : ",i); fun(); } } | ||
| |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF5C) : size(8) child[0] is vptr, points to vtbl 0x0041587C child[1] is Age : 8 vtbl[0] : I am child vtbl[1] : study... | 打印结果 |
|
内存布局 | Child Size:8B |vptr|age| | 内存布局 |
|
Vtbl | |Child::who()| |Child::study()| | Vtbl |
|
其他 | Vtbl存在堆上 | 其他 |
|
单一继承
单一继承 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} void fishing(){ printf("GrandFather go to fishing...\n");} int age; };
class Father:public GrandFather{ public: Father():age(36){} void cutting(){ printf("Father go to cutting...\n");} int age; };
class Child:public Father{ public: Child():age(8){} void studying(){ printf("Child go to studying...\n");} int age; };
int main(){ Child child; printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] is GrandFather : %d\n", ((int *)(&child))[0]); printf("child[1] is Father : %d\n", ((int *)(&child))[1]); printf("child[2] is child : %d\n", ((int *)(&child))[2]); } | ||
GrandFather ↑ Father ↑ Child
| |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF58) : size(12) child[0] is GrandFather : 60 child[1] is Father : 36 child[2] is child : 8 | 打印结果 |
|
内存布局 | Child Size:12B |GrandFather::age| |Father::age| |Child::age| | 内存布局 |
|
Vtbl |
| Vtbl |
|
其他 |
| 其他 |
|
单一继承&多态
单一继承&多态 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} virtual void who(){ printf("I am GrandFather\n");} virtual void fishing(){ printf("GrandFather go to fishing...\n");} virtual void hungry(){ printf("GrandFather is hungry\n");} int age; };
class Father:public GrandFather{ public: Father():age(36){} virtual void who(){ printf("I am Father\n");} virtual void cutting(){ printf("Father go to cutting...\n");} virtual void hungry(){ printf("Father is hungry\n");} int age; };
class Child : public Father{ public: Child():age(8){} virtual void who(){ printf("I am Child\n");} virtual void studying(){ printf("Child go to studying...\n");} virtual void hungry(){ printf("Child is hungry\n");} int age; };
int main(){
Child child; Fun fun = NULL; int * vtbl = (int *)(*((int*)&child));
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] is vptr, points to vtbl 0x%p\n",vtbl); printf("child[1] is GrandFather : %d\n", ((int *)(&child))[1]); printf("child[2] is Father : %d\n", ((int *)(&child))[2]); printf("child[3] is child : %d\n", ((int *)(&child))[3]);
for (int i=0; (Fun)vtbl[i]!=NULL;i++){ fun = (Fun)vtbl[i]; printf("vtbl[%d] : ",i); fun(); } } | ||
GrandFather ↑ Father ↑ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF54) : size(16) child[0] is vptr, points to vtbl 0x004157FC child[1] is GrandFather : 60 child[2] is Father : 36 child[3] is child : 8 vtbl[0] : I am Child vtbl[1] : GrandFather go to fishing... vtbl[2] : Child is hungry vtbl[3] : Father go to cutting... vtbl[4] : Child go to studying... | 打印结果 |
|
内存布局 | Child Size:16B |vptr| |GrandFather::age| |Father::age| |Child::age| | 内存布局 |
|
Vtbl | |Child::who()| |GrandFather::fishing()| | Child::hungry()| |Father::cutting()| |Child::studying()| | Vtbl |
|
其他 | 虚函数顺序是从base开始遍历 | 其他 |
|
多重继承
多重继承 | #include <stdio.h>
class GrandFather{ public: GrandFather():age(60){} int age; };
class Grandad{ public: Grandad():age(57){} int age; };
class Father:public GrandFather{ public: Father():age(36){} int age; };
class Mother:public Grandad{ public: Mother():age(34){} int age; };
class Child : public Father, public Mother{ public: Child():age(8){} int age; };
int main(){
Child child; int* pchild = (int *)&child;
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] GrandFather : %d\n",pchild[0]); printf("child[1] Father : %d\n",pchild[1]); printf("child[2] Grandad : %d\n",pchild[2]); printf("child[3] Mother : %d\n",pchild[3]); printf("child[4] Child : %d\n",pchild[4]); } | ||
GrandFathe Grandad ^ ^ Father Mother ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF50) : size(20) child[0] : 60 child[1] : 36 child[2] : 57 child[3] : 34 child[4] : 8 | 打印结果 |
|
内存布局 | Child Size:20B |GrandFather::age| |Father::age| |Grandad::age| |Mother::age| |Child::age| | 内存布局 |
|
Vtbl |
| Vtbl |
|
其他 |
| 其他 |
|
多重继承&多态
多重继承&多态 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} virtual void who(){ printf("I am GrandFather\n");} virtual void fishing(){ printf("GrandFather go to fishing...\n");} virtual void hungry(){ printf("GrandFather is hungry\n");} int age; };
class Grandad{ public: Grandad():age(57){} virtual void who(){ printf("I am Grandad\n");} virtual void chessing(){ printf("Grandad go to chessing...\n");} virtual void hungry(){ printf("Grandad is hungry\n");} int age; };
class Father:public GrandFather{ public: Father():age(36){} virtual void who(){ printf("I am Father\n");} virtual void cutting(){ printf("Father go to cutting...\n");} virtual void hungry(){ printf("Father is hungry\n");} int age; };
class Mother:public Grandad{ public: Mother():age(34){} virtual void who(){ printf("I am Mother\n");} virtual void sewing(){ printf("Mother go to sewing...\n");} virtual void hungry(){ printf("Mother is hungry\n");} int age; };
class Child : public Father, public Mother{ public: Child():age(8){} virtual void who(){ printf("I am Child\n");} virtual void studying(){ printf("Child go to studying...\n");} virtual void hungry(){ printf("Child is hungry\n");} int age; };
int main(){
Child child; int* pchild = (int *)&child;
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] vptr1 : 0x%p\n",pchild[0]); printf("child[1] GrandFather : %d\n",pchild[1]); printf("child[2] Father : %d\n",pchild[2]); printf("child[3] vptr2 : 0x%p\n",pchild[3]); printf("child[4] Grandad : %d\n",pchild[4]); printf("child[5] Mother : %d\n",pchild[5]); printf("child[6] Child : %d\n",pchild[6]);
Fun fun = NULL; int * vtbl1 = (int *)pchild[0]; for (int i=0; (Fun)vtbl1[i]!=NULL; i++){ fun = (Fun)vtbl1[i]; printf("vtbl1[%d] : ", i); fun(); }
int * vtbl2 = (int *)pchild[3]; for (int i=0; (Fun)vtbl2[i]!=NULL; i++){ fun = (Fun)vtbl2[i]; printf("vtbl2[%d] : ", i); fun(); } } | ||
GrandFathe Grandad ^ ^ Father Mother ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF48) : size(28) child[0] vptr1 : 0x00416864 child[1] GrandFather : 60 child[2] Father : 36 child[3] vptr2 : 0x0041684C child[4] Grandad : 57 child[5] Mother : 34 child[6] Child : 8 vtbl1[0] : I am Child vtbl1[1] : GrandFather go to fishing... vtbl1[2] : Child is hungry vtbl1[3] : Father go to cutting... vtbl1[4] : Child go to studying... vtbl2[0] : I am Child vtbl2[1] : Grandad go to chessing... vtbl2[2] : Child is hungry vtbl2[3] : Mother go to sewing... | 打印结果 |
|
内存布局 | Child Size:28B |vptr1| |GrandFather::age| |Father::age| |vptr2| |Grandad::age| |Mother::age| |Child::age| | 内存布局 |
|
Vtbl | Vtbl1: |Child::who()| |GrandFather::age| |Child::hungry()| |Father::cutting()| |Child::studying()| Vtbl2: |Child::who()| |Grandad::chessing()| |Child::hungry()| |Mother::sewing()| | Vtbl |
|
其他 | Child的独有虚函数,如studying,只在base1的vtbl进行记录。 | 其他 |
|
单一虚拟继承
单一虚拟继承 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} int age; };
class Father : virtual public GrandFather{ public: Father():age(36){} int age; };
class Child : public Father{ public: Child():age(8){} int age; };
int main(){ Child child; int* pchild = (int *)&child; int* pFather = (int*)pchild[0];//指向virtual base subobject的指针
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] pFather : 0x%p\n",pchild[0]); printf("child[1] Father : %d\n",pchild[1]); printf("child[2] Child : %d\n",pchild[2]); /*通过pchild和pFather获得偏移量都可以获得virtual base 数据*/ printf("child[3] GrandFather : %d %d\n", pchild[3], *(int*)(((char *)pchild)+pFather[1])); printf("pFather[0] : 0x%p\n",pFather[0], pFather[1]); printf("pFather[1] Offset : %d\n", pFather[1]); } | ||
GrandFather ^ Father ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF54) : size(16) child[0] pFather : 0x00415758 child[1] Father : 36 child[2] Child : 8 child[3] GrandFather : 60 60 pFather[0] : 0x00000000 pFather[1] Offset : 12 | 打印结果 |
|
内存布局 | Child Size:16B |vbase_pointer| pointer to vbase |Father::age| |Child::age| |GrandFather::age| | 内存布局 |
|
vbase | |vptr offset from vbase_pointer| |vbase offset from vbase_pointer| |
|
|
Vtbl |
| Vtbl |
|
其他 | 寻址Virtual base object和Derivedvptr是通过offset来得到的 | 其他 |
|
单一虚拟继承&多态
案例一
单一虚拟继承&多态 一 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} void fishing(){ printf("GrandFather go to fishing...\n");} int age; };
class Father : virtual public GrandFather{ public: Father():age(36){} virtual void who(){ printf("I am Father\n");} virtual void cutting(){ printf("Father go to cutting...\n");} virtual void hungry(){ printf("Father is hungry\n");} int age; };
class Child : public Father{ public: Child():age(8){} virtual void who(){ printf("I am Child\n");} virtual void studying(){ printf("Child go to studying...\n");} virtual void hungry(){ printf("Child is hungry\n");} int age; };
int main(){ Child child; Fun fun = NULL; int* pchild = (int *)&child; int* vbase_pointer = (int*)pchild[1]; int* vtbl = (int *)pchild[0];
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] vtbl : 0x%p\n", vtbl); printf("child[1] vbase_pointer : 0x%p\n", vbase_pointer); printf("child[2] Father : %d\n", pchild[2]); printf("child[3] Child : %d\n", pchild[3]); printf("child[4] GrandFather : %d\n", pchild[4]);
printf("vbase_pointer[0] : %d\n", vbase_pointer[0]); printf("vbase_pointer[1] vbase offset : %d\n", vbase_pointer[1]);
for (int i=0; (Fun)vtbl[i]!=NULL; i++){ fun = (Fun)vtbl[i]; printf("vtbl[%d] : ", i); fun(); } } | ||
GrandFather ^ Father ^ Child
| |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF50) : size(20) child[0] vtbl : 0x00415778 child[1] vbase_pointer : 0x004164D8 child[2] Father : 36 child[3] Child : 8 child[4] GrandFather : 60 vbase_pointer[0] : -4 vbase_pointer[1] vbase offset : 12 vtbl[0] : I am Child vtbl[1] : Father go to cutting... vtbl[2] : Child is hungry vtbl[3] : Child go to studying... | 打印结果 |
|
内存布局 | Child Size : 20B |vptr| |vbase_pointer| |Father::age| |Child::age| |GrandFather::age| | 内存布局 |
|
Vtbl | |Child::who()| |Father::cutting()| |Child::hungry()| |Child::studying()| | Vtbl |
|
Vbase_table | |vptr offset from vbase_pointer| |vbase offset from vbase_pointer| |
|
|
其他 |
| 其他 |
|
案例二
单一虚拟继承&多态 二 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} virtual void fishing(){ printf("GrandFather go to fishing...\n");} int age; };
class Father : virtual public GrandFather{ public: Father():age(36){} virtual void who(){ printf("I am Father\n");} virtual void cutting(){ printf("Father go to cutting...\n");} virtual void hungry(){ printf("Father is hungry\n");} int age; };
class Child : public Father{ public: Child():age(8){} virtual void who(){ printf("I am Child\n");} virtual void studying(){ printf("Child go to studying...\n");} virtual void hungry(){ printf("Child is hungry\n");} int age; };
int main(){ Child child; Fun fun = NULL; int* pchild = (int *)&child; int* vbase_pointer = (int*)pchild[1]; int* vtbl = (int *)pchild[0]; int* vbase_vtbl = (int *)pchild[4];
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] vtbl : 0x%p\n", vtbl); printf("child[1] vbase_pointer : 0x%p\n", vbase_pointer); printf("child[2] Father : %d\n", pchild[2]); printf("child[3] Child : %d\n", pchild[3]); printf("child[4] GrandFather vtbl : 0x%p\n", vbase_vtbl); printf("child[5] GrandFather : %d\n", pchild[5]);
printf("vbase_pointer[0] : %d\n", vbase_pointer[0]); printf("vbase_pointer[1] vbase offset : %d\n", vbase_pointer[1]);
for (int i=0; (Fun)vtbl[i]!=NULL; i++){ fun = (Fun)vtbl[i]; printf("vtbl[%d] : ", i); fun(); }
for (int i=0; (Fun)vbase_vtbl[i]!=NULL; i++){ fun = (Fun)vbase_vtbl[i]; printf("vbase_vtbl[%d] : ", i); fun(); } } | ||
GrandFather ^ Father ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF4C) : size(24) child[0] vtbl : 0x0041577C child[1] vbase_pointer : 0x0041640C child[2] Father : 36 child[3] Child : 8 child[4] GrandFather vtbl : 0x0041594C child[5] GrandFather : 60 vbase_pointer[0] : -4 vbase_pointer[1] vbase offset : 12 vtbl[0] : I am Child vtbl[1] : Father go to cutting... vtbl[2] : Child is hungry vtbl[3] : Child go to studying... vbase_vtbl[0] : GrandFather go to fishing... | 打印结果 |
|
内存布局 | Child Size : 24B |vptr| |vbase_pointer| |Father::age| |Child::age| |GrandFather::vptr| |GrandFather::age| | 内存布局 |
|
Vtbl | Child vptr: |Child::who()| |Father::cutting()| |Child::hungry()| |Child::studying()| GrandFather vptr: |GrandFather::fishing()| | Vtbl |
|
Vbase_table | |vptr offset from vbase_pointer| |vbase offset from vbase_pointer| |
|
|
其他 |
| 其他 |
|
案例三
单一虚拟继承&多态 三 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} virtual void who(){ printf("I am GrandFather\n");} virtual void fishing(){ printf("GrandFather go to fishing...\n");} int age; };
class Father : virtual public GrandFather{ public: Father():age(36){} virtual void who(){ printf("I am Father\n");} virtual void cutting(){ printf("Father go to cutting...\n");} virtual void hungry(){ printf("Father is hungry\n");} int age; };
class Child : public Father{ public: Child():age(8){} virtual void who(){ printf("I am Child\n");} virtual void studying(){ printf("Child go to studying...\n");} virtual void hungry(){ printf("Child is hungry\n");} int age; };
int main(){ Child child; Fun fun = NULL; int* pchild = (int *)&child; int* vbase_pointer = (int*)pchild[1]; int* vtbl = (int *)pchild[0]; int* vbase_vtbl = (int *)pchild[5];
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] vtbl : 0x%p\n", vtbl); printf("child[1] vbase_pointer : 0x%p\n", vbase_pointer); printf("child[2] Father : %d\n", pchild[2]); printf("child[3] Child : %d\n", pchild[3]); printf("child[4] : %.8x\n", pchild[4]); printf("child[5] GrandFather vtbl : 0x%p\n", vbase_vtbl); printf("child[6] GrandFather : %d\n", pchild[6]);
printf("vbase_pointer[0] : %d\n", vbase_pointer[0]); printf("vbase_pointer[1] vbase offset : %d\n", vbase_pointer[1]);
for (int i=0; i<3; i++){ fun = (Fun)vtbl[i]; printf("vtbl[%d]: ",i); fun(); }
for (int i=1; (Fun)vbase_vtbl[i]!=NULL; i++){ fun = (Fun)vbase_vtbl[i]; printf("vbase_vtbl[%d]: ", i); fun(); } } | ||
GrandFather ^ Father ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF48) : size(28) child[0] vtbl : 0x00416410 child[1] vbase_pointer : 0x004158BC child[2] Father : 36 child[3] Child : 8 child[4] : 00000000 child[5] GrandFather vtbl : 0x0041577C child[6] GrandFather : 60 vbase_pointer[0] : -4 vbase_pointer[1] vbase offset : 16 vtbl[0]: Father go to cutting... vtbl[1]: Child is hungry vtbl[2]: Child go to studying... vbase_vtbl[1]: GrandFather go to fishing... | 打印结果 |
|
内存布局 | Child Size : 28B |vptr| |vbase_pointer| |Father::age| |Child::age| |NULL| |GrandFather::vptr| |GrandFather::age| | 内存布局 |
|
Vtbl | Child vptr: |Father::cutting()| |Child::hungry()| |Child::studying()| GrandFather vptr: |GrandFather::fishing()| | Vtbl |
|
Vbase_table | |vptr offset from vbase_pointer| |vbase offset from vbase_pointer| |
|
|
其他 |
| 其他 |
|
多重虚拟继承
多重虚拟继承 | #include <stdio.h>
class GrandFather{ public: GrandFather():age(60){} int age; };
class Father : virtual public GrandFather{ public: Father():age(36){} int age; };
class Mother : virtual public GrandFather{ public: Mother():age(34){} int age; };
class Child : public Father, public Mother{ public: Child():age(8){} int age; };
int main(){
Child child; int* pchild = (int *)&child; int* Father_vbase_pointer = (int *)pchild[0]; int* Mother_vbase_pointer = (int *)pchild[2];
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] Father_vbase_pointer : %p\n",pchild[0]); printf("child[1] Father : %d\n",pchild[1]); printf("child[2] Mother_vbase_pointer : %p\n",pchild[2]); printf("child[3] Mother : %d\n",pchild[3]); printf("child[4] Child : %d\n",pchild[4]); printf("child[5] GrandFather : %d\n",pchild[5]);
printf("Father_vbase_pointer[0] : %d\n",Father_vbase_pointer[0]); printf("Father_vbase_pointer[1] vbase offset : %d\n",Father_vbase_pointer[1]); printf("Mother_vbase_pointer[0] : %d\n",Mother_vbase_pointer[0]); printf("Mother_vbase_pointer[1] vbase offset : %d\n",Mother_vbase_pointer[1]); } | ||
GrandFather ^ ^ Father Mother ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF4C) : size(24) child[0] Father_vbase_pointer : 00415784 child[1] Father : 36 child[2] Mother_vbase_pointer : 0041577C child[3] Mother : 34 child[4] Child : 8 child[5] GrandFather : 60 Father_vbase_pointer[0] : 0 Father_vbase_pointer[1] vbase offset : 20 Mother_vbase_pointer[0] : 0 Mother_vbase_pointer[1] vbase offset : 12 | 打印结果 |
|
内存布局 | Child Size : 24B |Father_vbase_pointer| |Father::age| |Mother_vbase_pointer| |Mother::age| |Child::age| |GrandFather::age| | 内存布局 |
|
Vtbl |
| Vtbl |
|
Vbase_table | Father Vbase table |Father vptr offset from Father_vbase_pointer | |vbase offset from Father_vbase_pointer | Mother Vbase table |Mother vptr offset from Mother_vbase_pointer | |vbase offset from Mother_vbase_pointer | |
|
|
其他 |
| 其他 |
|
多重虚拟继承&多态
案例一
多重虚拟继承&多态 一 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} int age; };
class Father : virtual public GrandFather{ public: Father():age(36){} virtual void who(){ printf("I am Father\n");} virtual void cutting(){ printf("Father go to cutting...\n");} virtual void hungry(){ printf("Father is hungry\n");} int age; };
class Mother : virtual public GrandFather{ public: Mother():age(34){} virtual void who(){ printf("I am Mother\n");} virtual void sewing(){ printf("Mother go to sewing...\n");} virtual void hungry(){ printf("Mother is hungry\n");} int age; };
class Child : public Father, public Mother{ public: Child():age(8){} virtual void who(){ printf("I am Child\n");} virtual void studying(){ printf("Child go to studying...\n");} virtual void hungry(){ printf("Child is hungry\n");} int age; };
int main(){
Child child; int* pchild = (int *)&child; int* Father_vtbl = (int *)pchild[0]; int* Father_vbase_pointer = (int *)pchild[1]; int* Mother_vtbl = (int *)pchild[3]; int* Mother_vbase_pointer = (int *)pchild[4];
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] Father_vtbl : %p\n",Father_vtbl); printf("child[1] Father_vbase_pointer : %p\n",Father_vbase_pointer); printf("child[2] Father : %d\n",pchild[2]); printf("child[3] Mother_vtbl : %d\n",Mother_vtbl); printf("child[4] Mother_vbase_pointer : %d\n",Mother_vbase_pointer); printf("child[5] Mother : %d\n",pchild[5]); printf("child[6] Child : %d\n",pchild[6]); printf("child[7] GrandFather : %d\n",pchild[7]);
printf("Father_vbase_pointer[0] : %d\n",Father_vbase_pointer[0]); printf("Father_vbase_pointer[1] vbase offset : %d\n",Father_vbase_pointer[1]); printf("Mother_vbase_pointer[0] : %d\n",Mother_vbase_pointer[0]); printf("Mother_vbase_pointer[1] vbase offset : %d\n",Mother_vbase_pointer[1]);
Fun fun = NULL; for (int i=0; i<4; i++){ fun = (Fun)Father_vtbl[i]; printf("Father_vtbl[%d] : ", i); fun(); }
for (int i=0; (Fun)Mother_vtbl[i]!=NULL; i++){ fun = (Fun)Mother_vtbl[i]; printf("Mother_vtbl[%d] : ", i); fun(); } } | ||
GrandFather ^ ^ Father Mother ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF44) : size(32) child[0] Father_vtbl : 004168AC child[1] Father_vbase_pointer : 00416980 child[2] Father : 36 child[3] Mother_vtbl : 4286780 child[4] Mother_vbase_pointer : 4286800 child[5] Mother : 34 child[6] Child : 8 child[7] GrandFather : 60 Father_vbase_pointer[0] : -4 Father_vbase_pointer[1] vbase offset : 24 Mother_vbase_pointer[0] : -4 Mother_vbase_pointer[1] vbase offset : 12 Father_vtbl[0] : I am Child Father_vtbl[1] : Father go to cutting... Father_vtbl[2] : Child is hungry Father_vtbl[3] : Child go to studying... Mother_vtbl[0] : I am Child Mother_vtbl[1] : Mother go to sewing... Mother_vtbl[2] : Child is hungry | 打印结果 |
|
内存布局 | Child Size : 32B |Father vptr| |Father_vbase_pointer| |Father::age| |Mother vptr| |Mother_vbase_pointer| |Mother::age| |Child::age| |GrandFather::age| | 内存布局 |
|
Vtbl | Father vtbl |Child::who()| |Father::cutting()| |Child::hungry()| |Child::studying()| Mother vtbl |Child::who()| |Mother::sewing()| |Child::hungry()| | Vtbl |
|
Vbase_table | Father Vbase table |Father vptr offset from Father_vbase_pointer | |vbase offset from Father_vbase_pointer | Mother Vbase table |Mother vptr offset from Mother_vbase_pointer | |vbase offset from Mother_vbase_pointer | |
|
|
其他 | Child::studying()只需要在第一个base中记录即可。 | 其他 |
|
案例二
多重虚拟继承&多态 二 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} virtual void fishing(){ printf("GrandFather go to fishing...\n");} int age; };
class Father : virtual public GrandFather{ public: Father():age(36){} virtual void who(){ printf("I am Father\n");} virtual void cutting(){ printf("Father go to cutting...\n");} virtual void hungry(){ printf("Father is hungry\n");} int age; };
class Mother : virtual public GrandFather{ public: Mother():age(34){} virtual void who(){ printf("I am Mother\n");} virtual void sewing(){ printf("Mother go to sewing...\n");} virtual void hungry(){ printf("Mother is hungry\n");} int age; };
class Child : public Father, public Mother{ public: Child():age(8){} virtual void who(){ printf("I am Child\n");} virtual void studying(){ printf("Child go to studying...\n");} virtual void hungry(){ printf("Child is hungry\n");} int age; };
int main(){
Child child; int* pchild = (int *)&child; int* Father_vtbl = (int *)pchild[0]; int* Father_vbase_pointer = (int *)pchild[1]; int* Mother_vtbl = (int *)pchild[3]; int* Mother_vbase_pointer = (int *)pchild[4]; int* GrandFather_vtbl = (int *)pchild[7];
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] Father_vtbl : %p\n",Father_vtbl); printf("child[1] Father_vbase_pointer : %p\n",Father_vbase_pointer); printf("child[2] Father : %d\n",pchild[2]); printf("child[3] Mother_vtbl : %d\n",Mother_vtbl); printf("child[4] Mother_vbase_pointer : %d\n",Mother_vbase_pointer); printf("child[5] Mother : %d\n",pchild[5]); printf("child[6] Child : %d\n",pchild[6]); printf("child[7] GrandFather_vtbl : %d\n",GrandFather_vtbl); printf("child[8] GrandFather : %d\n",pchild[8]);
printf("Father_vbase_pointer[0] : %d\n",Father_vbase_pointer[0]); printf("Father_vbase_pointer[1] vbase offset : %d\n",Father_vbase_pointer[1]); printf("Mother_vbase_pointer[0] : %d\n",Mother_vbase_pointer[0]); printf("Mother_vbase_pointer[1] vbase offset : %d\n",Mother_vbase_pointer[1]);
Fun fun = NULL; for (int i=0; i<4; i++){ fun = (Fun)Father_vtbl[i]; printf("Father_vtbl[%d] : ", i); fun(); }
for (int i=0; i<3; i++){ fun = (Fun)Mother_vtbl[i]; printf("Mother_vtbl[%d] : ", i); fun(); }
for (int i=0; i<3; i++){ fun = (Fun)GrandFather_vtbl[i]; printf("GrandFather_vtbl[%d] : ", i); fun(); } } | ||
GrandFather ^ ^ Father Mother ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF40) : size(36) child[0] Father_vtbl : 00416898 child[1] Father_vbase_pointer : 00416D34 child[2] Father : 36 child[3] Mother_vtbl : 4286768 child[4] Mother_vbase_pointer : 4286740 child[5] Mother : 34 child[6] Child : 8 child[7] GrandFather_vtbl : 4286788 child[8] GrandFather : 60 Father_vbase_pointer[0] : -4 Father_vbase_pointer[1] vbase offset : 24 Mother_vbase_pointer[0] : -4 Mother_vbase_pointer[1] vbase offset : 12 Father_vtbl[0] : I am Child Father_vtbl[1] : Father go to cutting... Father_vtbl[2] : Child is hungry Father_vtbl[3] : Child go to studying... Mother_vtbl[0] : I am Child Mother_vtbl[1] : Mother go to sewing... Mother_vtbl[2] : Child is hungry GrandFather_vtbl[0] : GrandFather go to fishing... | 打印结果 |
|
内存布局 | Child Size : 36B |Father vptr| |Father_vbase_pointer| |Father::age| |Mother vptr| |Mother_vbase_pointer| |Mother::age| |Child::age| |GrandFather vptr| |GrandFather::age| | 内存布局 |
|
Vtbl | Father vtbl |Child::who()| |Father::cutting()| |Child::hungry()| |Child::studying()| Mother vtbl |Child::who()| |Mother::sewing()| |Child::hungry()| GrandFather vptr | GrandFather::fishing()| | Vtbl |
|
Vbase_table | Father Vbase table |Father vptr offset from Father_vbase_pointer | |vbase offset from Father_vbase_pointer | Mother Vbase table |Mother vptr offset from Mother_vbase_pointer | |vbase offset from Mother_vbase_pointer | |
|
|
其他 |
| 其他 |
|
案例三
多重虚拟继承&多态 三 | #include <stdio.h> typedef void(*Fun)(void);
class GrandFather{ public: GrandFather():age(60){} virtual void who(){ printf("I am GrandFather\n");} virtual void fishing(){ printf("GrandFather go to fishing...\n");} int age; };
class Father : virtual public GrandFather{ public: Father():age(36){} virtual void who(){ printf("I am Father\n");} virtual void cutting(){ printf("Father go to cutting...\n");} virtual void hungry(){ printf("Father is hungry\n");} int age; };
class Mother : virtual public GrandFather{ public: Mother():age(34){} virtual void who(){ printf("I am Mother\n");} virtual void sewing(){ printf("Mother go to sewing...\n");} virtual void hungry(){ printf("Mother is hungry\n");} int age; };
class Child : public Father, public Mother{ public: Child():age(8){} virtual void who(){ printf("I am Child\n");} virtual void studying(){ printf("Child go to studying...\n");} virtual void hungry(){ printf("Child is hungry\n");} int age; };
int main(){
Child child; int* pchild = (int *)&child; int* Father_vtbl = (int *)pchild[0]; int* Father_vbase_pointer = (int *)pchild[1]; int* Mother_vtbl = (int *)pchild[3]; int* Mother_vbase_pointer = (int *)pchild[4]; int* GrandFather_vtbl = (int *)pchild[8];
printf("child(0x%p) : size(%d)\n",&child,sizeof(child)); printf("child[0] Father_vtbl : %p\n",Father_vtbl); printf("child[1] Father_vbase_pointer : %p\n",Father_vbase_pointer); printf("child[2] Father : %d\n",pchild[2]); printf("child[3] Mother_vtbl : %d\n",Mother_vtbl); printf("child[4] Mother_vbase_pointer : %d\n",Mother_vbase_pointer); printf("child[5] Mother : %d\n",pchild[5]); printf("child[6] Child : %d\n",pchild[6]); printf("child[7] : %d\n",pchild[7]); printf("child[8] GrandFather_vtbl : %d\n",GrandFather_vtbl); printf("child[9] GrandFather : %d\n",pchild[9]);
printf("Father_vbase_pointer[0] : %d\n",Father_vbase_pointer[0]); printf("Father_vbase_pointer[1] vbase offset : %d\n",Father_vbase_pointer[1]); printf("Mother_vbase_pointer[0] : %d\n",Mother_vbase_pointer[0]); printf("Mother_vbase_pointer[1] vbase offset : %d\n",Mother_vbase_pointer[1]);
Fun fun = NULL; for (int i=0; i<3; i++){ fun = (Fun)Father_vtbl[i]; printf("Father_vtbl[%d] : ", i); fun(); }
for (int i=0; i<2; i++){ fun = (Fun)Mother_vtbl[i]; printf("Mother_vtbl[%d] : ", i); fun(); }
for (int i=1; i<3; i++){ fun = (Fun)GrandFather_vtbl[i]; printf("GrandFather_vtbl[%d] : ", i); fun(); } } | ||
GrandFather ^ ^ Father Mother ^ Child | |||
X86 VC++ | X86 g++ | ||
打印结果 | child(0x0012FF3C) : size(40) child[0] Father_vtbl : 004168A4 child[1] Father_vbase_pointer : 00416F00 child[2] Father : 36 child[3] Mother_vtbl : 4286616 child[4] Mother_vbase_pointer : 4287796 child[5] Mother : 34 child[6] Child : 8 child[7] : 0 child[8] GrandFather_vtbl : 4286768 child[9] GrandFather : 60 Father_vbase_pointer[0] : -4 Father_vbase_pointer[1] vbase offset : 28 Mother_vbase_pointer[0] : -4 Mother_vbase_pointer[1] vbase offset : 16 Father_vtbl[0] : Father go to cutting... Father_vtbl[1] : Child is hungry Father_vtbl[2] : Child go to studying... Mother_vtbl[0] : Mother go to sewing... Mother_vtbl[1] : Child is hungry GrandFather_vtbl[1] : GrandFather go to fishing... | 打印结果 |
|
内存布局 | Child Size : 40B |Father vptr| |Father_vbase_pointer| |Father::age| |Mother vptr| |Mother_vbase_pointer| |Mother::age| |Child::age| |NULL| |GrandFather vptr| |GrandFather::age| | 内存布局 |
|
Vtbl | Father vtbl |Father::cutting()| |Child::hungry()| |Child::studying()| Mother vtbl |Mother::sewing()| |Child::hungry()| GrandFather vptr | GrandFather::fishing()| | Vtbl |
|
其他 |
| 其他 |
|
特别内存布局
同类型对象共用一个虚函数表
#include <stdio.h>
class Father{
public:
Father():age(36){}
virtual void who(){ printf("I am Father\n");}
int age;
};
class Child : public Father{
public:
Child():age(8){}
virtual void who(){ printf("I am Child\n");}
int age;
};
int main(){
Father father;
Child child1, child2;
printf("father(0x%p) child1(0x%p) child2(0x%p)\n",&father, &child1, &child2);
printf("father vptr is 0x%p\n", *(int *)&father);
printf("child1 vptr is 0x%p\n", *(int *)&child1);
printf("child2 vptr is 0x%p\n", *(int *)&child2);
}
father vptr is 0x004157B0
child1 vptr is 0x00415758
child2 vptr is 0x00415758
同类型对象共用一个虚基类的指针
#include <stdio.h>
class Father{
public:
Father():age(36){}
int age;
};
class Child : virtual public Father{
public:
Child():age(10){}
int age;
};
int main(){
Father father;
Child child1, child2;
printf("father Size(%d) child1 Size(%d) child2 Size(%d)\n",sizeof(father), sizeof(child1), sizeof(child2));
printf("child1 vbase_pointer is 0x%p, age is %d\n", *(int *)&child1, *((int *)&child1+1));
printf("child2 vbase_pointer is 0x%p, age is %d\n", *(int *)&child2, *((int *)&child2+1));
printf("Child object vbase offset is %d\n", *((int *)(*(int *)&child1)+1));
}
结果:
child1 vbase_pointer is 0x00415768, age is 10
child2 vbase_pointer is 0x00415768, age is 10
Child object vbase offset is 8
Base Class Subobject在Derived Class中有完整原样性
#include <stdio.h>
class Father{
public:
Father():age('f'){}
virtual void who(){ printf("I am Father\n");}
char age;
};
class Child : public Father{
public:
Child():age('c'){}
virtual void who(){ printf("I am Child\n");}
char age;
};
int main(){
Child child;
printf("child(0x%p) size(%d)\n",&child, sizeof(child));
printf("child.Father::age(0x%p)\n",&child.Father::age);
printf("child.age(0x%p)\n",&child.age);
}
结果:
child.Father::age(0x0012FF5C)
child.age(0x0012FF60)
指向virtual base Class指针
如虚拟多继承&多态案例三的内存布局Child Size : 40B
|Father vptr|
|Father_vbase_pointer|
|Father::age|
|Mother vptr|
|Mother_vbase_pointer|
|Mother::age|
|Child::age|
|NULL|
|GrandFather vptr|
|GrandFather::age|Father Vbase table
|Father vptr offsetfrom Father_vbase_pointer | -4
|vbase offset from Father_vbase_pointer| 28
Mother Vbase table
|Mother vptr offsetfrom Mother_vbase_pointer | -4
|vbase offset from Mother_vbase_pointer | 16