CSDN博客

img wxcwuxuchun

C++对象模型之简单对象模型(2)

发表于2004/1/27 21:09:00  784人阅读

分类: C++

1.3.   包含方法的对象

包含了方法的对象,其大小和内存布局应该是什么样子的呢?下面让我们来看一看。

1.3.1. 不包含虚函数的对象

考察下面的类:

class Simple

{

public :

  Simple(char _a, int _i);

private :

  char a;

  int i;

};

它的大小应该是多少呢?数据占用了8个字节,函数应该占用多少呢?我们来做个测试。这一次让人惊异的是它的大小没发生变化,仍然是8。那么它的内存布局应该是

char a 1 Byte

补齐占位(3 Byte

int i 4 Byte

 

Simple(char _a, int _i)

Simple对象内存布局

这样的内存布局对不对呢?让我们设计一个程序验证一下。

0001   #include <iostream>

0002   #include <conio.h>

0003   using namespace std;

0004   //----------------------------------------------------------------

0005   class Simple

0006   {

0007   public :

0008     Simple(char _a, int _i);

0009   private :

0010     char a;

0011     int i;

0012   };

0013   //----------------------------------------------------------------

0014   Simple::Simple(char _a, int _i)

0015   {

0016     a = _a;

0017     i = _i;

0018   }

0019   //----------------------------------------------------------------

0020   int main(int argccharargv[])

0021   {

0022     cout << "Sizeof(Simple)" << '/t' << sizeof(Simple) << endl;

0023     Simple a('c', 9);

0024     int *ip = (int *)&a;

0025     char *cp = (char *)&a;

0026     cout << "Simple.a" << '/t' << *cp << endl;

0027     cout << "Simple.i" << '/t' << *++ip << endl;

0028     getch();

0029     return 0;

0030   }

0031   //----------------------------------------------------------------

结果符合我们的猜测。

1.3.2. 包含虚函数的对象

考察下面的类:

class Simple

{

public :

  Simple(char _a, int _i);

  virtual void vPrint(void);

  void Print(void);

private :

  char a;

  int i;

};

这一次他的大小是多少呢?按照上面的经验,函数不占据对象的存储空间,那么他的大小应该是8。对不对呢?再来检验一次。结果怎么变成“12”了呢?慢着,让我们想一想,虚函数?它意味着什么呢?虚函数意味着多态性,也就是运行期才决定调用哪个函数。那么这时如何实现的呢?答案是virtual function table,也就是通常所说的虚函数表。通过virtual function table的间接引用,我们就可以在运行期间决定调用哪一个函数。那么如何能够获得virtual function table?这就需要用到一个叫做vtbl的指针,有这个指针指向virtual function table的开始地址,那么对于虚函数的调用就变成了通过virtual function table的引用,调用函数指针。当然,这对于执行期来将是有效率的代价的。包含虚函数的对象模型如下:

void vPrint(void)

char a 1 Byte

补齐占位(3 Byte

int i 4 Byte

vtbl 4 Byte

 


               数据布局                                    虚函数表

Simple(char _a, int _i)

 

void Print(void)

 

Simple对象内存布局

让我们对此作一个验证

0001   #include <iostream>

0002   #include <conio.h>

0003   using namespace std;

0004   //----------------------------------------------------------------

0005   class Simple

0006   {

0007   public :

0008     Simple(char _a, int _i);

0009     virtual void vPrint(void);

0010     void Print(void);

0011   private :

0012     char a;

0013     int i;

0014   };

0015   //----------------------------------------------------------------

0016   Simple::Simple(char _a, int _i)

0017   {

0018     a = _a;

0019     i = _i;

0020   }

0021   //----------------------------------------------------------------

0022   void Simple::Print(void)

0023   {

0024     cout << "Simple.a" << a << '/t' << "Simple.i" << i << endl;

0025   }

0026   //----------------------------------------------------------------

0027   void Simple::vPrint(void)

0028   {

0029     cout << "Simple.a" << a << '/t' << "Simple.i" << i << endl;

0030   }

0031   //----------------------------------------------------------------

0032   int main(int argccharargv[])

0033   {

0034     cout << "Sizeof(Simple)" << '/t' << sizeof(Simple) << endl;

0035     Simple a('c', 9);

0036     int *ip = (int *)&a;

0037     char *cp = (char *)&a;

0038     cout << "Simple.a" << '/t' << *cp << endl;

0039     cout << "Simple.i" << '/t' << *++ip << endl;

0040     cout << "Simple.vtbl" << '/t' << *++ip << endl;

0041     getch();

0042     return 0;

0043   }

0044   //----------------------------------------------------------------

程序的输出为:

Sizeof(Simple)  12

Simple.a        c

Simple.i        9

Simple.vtbl     4269384

非常符合我们的推测。以上是gcc的编译结果,在C++ Builder上,代码和结果略有不同

cout << "Sizeof(Simple)" << '/t' << sizeof(Simple) << endl;

Simple a('c', 9);

int *ip = (int *)&a;

char *cp = (char *)&a;

cout << "Simple.vtbl" << '/t' << *ip << endl;

cout << "Simple.a" << '/t' << *(cp+4) << endl;

cout << "Simple.i" << '/t' << *(ip+2) << endl;

程序的输出为:

Sizeof(Simple)  12

Simple.vtbl     4207548

Simple.a        c

Simple.i        9

    不同处在于vtbl在对象内存布局的开始处还是结尾处。
0 0

相关博文

我的热门文章

img
取 消
img