C++ 虚函数和多重继承的内存布局初探

C++ 对象的内存布局

一切以事实说话:

代码:

   1: #include <stdio.h> 

   2:  

   3: class A {

   4:   public:   

   5:     int a;

   6:     int b;  

   7:     int c;  

   8: };

   9:  

  10: int main(int argc, char** argv) {

  11:   A obj;

  12:   printf(" obj   :%p\n obj.a: %p \n obj.b: %p \n obj.c: %p\n" ,                                                          

  13:         &obj, &obj.a, &obj.b, &obj.c);

  14:   return 0;

  15: }

执行结果:

C++ 虚函数和多重继承的内存布局初探

不同的机器执行的结果可能不同,但是从这里的出的一个结论是:

对象的地址是整个类的起始地址(也就是低地址)。其成员的地址顺序和其在类中声明的顺序有关系。

而对上面的代码稍加修改,增加一个虚函数。

   1: #include <stdio.h>

   2:  

   3: class A { 

   4:   public:

   5:     virtual void show() {}                                                                                               

   6:     int a;

   7:     int b;

   8:     int c;

   9: };

  10:  

  11: int main(int argc, char** argv) {

  12:   A obj;

  13:   printf(" obj   :%p\n obj.a: %p \n obj.b: %p \n obj.c: %p\n" ,

  14:         &obj, &obj.a, &obj.b, &obj.c);

  15:   return 0;

  16: }

测试结果:

C++ 虚函数和多重继承的内存布局初探

这里是由于增加了一个虚函数表的指针(测试机器为64位系统,故指针为8个字节)。从这里可以看出,虚函数表指针在类的起始地址,这也是为了对于不同的类该地址的偏移相同。

   1: class X {

   2: };

   3: class Y {

   4:   public:

   5:     virtual void f() {};

   6: };

   7: class X1 : public virtual X {

   8: };

   9: class X2 : public virtual X {

  10: };

  11: class A1 : public X1, public X2 {

  12: };

  13: class X3 : public X {

  14: };

  15: class X4 : public X {

  16: };

  17: class A2 : public X3, public X4 {

  18: };

  19: class Y1 : public virtual Y {

  20: };

  21: class Y2 : public virtual Y {

  22: };

  23: class B1 : public Y1, public Y2 {

  24: };

  25: class Y3 : public Y {

  26: };

  27: class Y4 : public Y {

  28: };

  29: class B2 : public Y3, public Y4 {

  30: };

  31:  

  32: int main (int argc, char** argv) {

  33:   printf("sizeof(X) %lu\n", sizeof(X));

  34:   printf("sizeof(Y) %lu\n", sizeof(Y));

  35:   printf("sizeof(X1) %lu\n", sizeof(X1));

  36:   printf("sizeof(X2) %lu\n", sizeof(X2));

  37:   printf("sizeof(A1) %lu\n", sizeof(A1));

  38:   printf("sizeof(X3) %lu\n", sizeof(X3));

  39:   printf("sizeof(X4) %lu\n", sizeof(X4));

  40:   printf("sizeof(A2) %lu\n", sizeof(A2));

  41:   printf("sizeof(Y1) %lu\n", sizeof(Y1));

  42:   printf("sizeof(Y2) %lu\n", sizeof(Y2));

  43:   printf("sizeof(B1) %lu\n", sizeof(B1));

  44:   printf("sizeof(Y3) %lu\n", sizeof(Y3));

  45:   printf("sizeof(Y4) %lu\n", sizeof(Y4));

  46:   printf("sizeof(B2) %lu\n", sizeof(B2));

  47:   return 0;

  48: }        

执行结果:

C++ 虚函数和多重继承的内存布局初探

上面的测试结果得出的结论:

  1. 空类的大小不是0,而是1,这样是提供一个占位符,这样由空类创建出的两个对象的地址就会不同,以作区分。
  2. 当类不是空的时候,该占位符就不需要了,类的大小就是类中成员所需的空间大小

注: 本想深入一探究竟,不过这部分和编译器有很大的关系,非朝夕可以搞定。先写这么多,再多做了解后再补充吧。

refer:

http://blog.csdn.net/haoel/article/details/3081328

http://blog.csdn.net/haoel/article/details/3081385

http://blog.chinaunix.net/uid-22535463-id-2749544.html

上一篇:Oracle 异常处理


下一篇:安卓http源码查看器详解