c++class 内存布局
1 #include <iostream> 2 using namespace std; 3 class base1 4 { 5 int a; 6 double b; 7 char c; 8 }; 9 int main() 10 { 11 base1 b; 12 return 1; 13 }
vs输出class布局方法:先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存布局,如果写上/d1 reportSingleClassLayoutXXX(XXX为类名),则只会打出指定类XXX的内存布局
base1内存布局
1 #include <iostream> 2 using namespace std; 3 class animal 4 { 5 protected: 6 int age; 7 public: 8 virtual void print_age(void) = 0; 9 }; 10 class dog:public animal 11 { 12 public: 13 dog(){this->age = 2;} 14 ~dog(){} 15 virtual void print_age(void){cout<<"Wang,my age ="<< this->age<<endl;} 16 }; 17 class cat:public animal 18 { 19 public: 20 cat(){this->age = 1;} 21 ~cat(){} 22 virtual void print_age(void){cout<<"Miao,my age ="<< this->age<<endl;} 23 }; 24 int main(void) 25 { 26 cat kitty; 27 dog jd; 28 animal * pa; 29 int *p = (int*)(&kitty); 30 int *q = (int*)(&jd); 31 p[0] = q[0]; 32 cout<<p[1]<<endl; 33 cout<<q[1]<<endl; 34 pa = &kitty; 35 pa ->print_age(); 36 system("pause"); 37 return 0; 38 39 }
内存布局:
这个内存结构图分成了两个部分,上面是内存分布,下面是虚表,我们逐个看。VS所带编译器是把虚表指针放在了内存的开始处(0地址偏移),然后再是成员变量;下面生成了虚表,紧跟在&[classname]_meta后面的0表示,这张虚表对应的虚指针在内存中的分布,下面列出了虚函数,左侧的0是这个虚函数的序号,这里只有一个虚函数,所以只有一项,如果有多个虚函数,会有序号为1,为2的虚函数列出来。
编译器是在构造函数创建这个虚表指针以及虚表的。
那么编译器是如何利用虚表指针与虚表来实现多态的呢?是这样的,当创建一个含有虚函数的父类的对象时,编译器在对象构造时将虚表指针指向父类的虚函数;同样,当创建子类的对象时,编译器在构造函数里将虚表指针(子类只有一个虚表指针,它来自父类)指向子类的虚表(这个虚表里面的虚函数入口地址是子类的)。
输出结果: