揭迷"C++类的对象在内存的布局"

来源:互联网 发布:微信的数据挖掘应用 编辑:程序博客网 时间:2024/06/13 07:50

平时做开发使用的语言最多的是c++, class(类)是c++中必不可少的因素,除了熟悉它的用法外,也必须清楚它在内存中的样子,这篇文章就是简要介绍它内存中布局情况.

 

我们先来看一个简单的类:

 class Ex1

{

int var1;

int var2;

char var3;

public:

int get_var1();

};

 

这个类在内存中是这个样子的:

class Ex1size(12):

+---

0| var1

4| var2

| var3

| <alignment member> (size=3)

+---

 

最后一个类的成员变量后面有3个字节的填充,这是因为要求4字节对齐.在Visual C++中,类的成员变量是按照其声明的大小依次排列在内存中的.

 

那么, 如果在一个类中含有虚函数呢?

Class Ex2

{

int var1;

public:

virtual int get_sum(int x, int y);

virtual void reset_values();

};

 

下面是这个类在内存中的存在形式:

class Ex2 size(8):

+---

0| {vfptr}

4| var1

+---

 

注意指向虚函数表的指针(vfptr)是被添加在最前面的,而在虚函数表里面,各个虚函数是按照其声明的顺序排列的. 类Ex2的虚函数表如下:

Ex2::$vftalbe@:

0| &Ex2::get_sum

4| &Ex2::reset_values

 

当一个类是继承另一个类的话,情况又会怎么样呢? 下面讨论一个简单的单一继承关系

Class Ex3:public Ex2

{

int var1;

public:

void get_values();

};

 

在内存中这个类的情况是这样的:

Class Ex3size(12);

+----

| +--- (base class Ex2)

0| | {vfptr}

4| | var1

| +---

8| var1

+---

 

正如您所看到的,派生类只是简单的把基类嵌入到自己内部就完事了.但是万一要是有多重继承会有什么情况发生呢?

Class Ex4

{

int var1;

int var2;

public:

virtual void func1();

virtual void func2();

};

 

Class Ex5: public Ex2, Ex4

{

int var1;

public:

void func1();

virtual void v_ex5();

};

内存中的情况会是这样:

Class Ex5size(24):

+---

| +--- (base class Ex2)

0| | {vfptr}

4| | var1

| +---

| +--- (base class Ex4)

8| | {vfptr}

12| | var1

16| | var2

| +---

20| var1

+---

 

Ex5::$vftalbe@Ex2@:

0| &Ex2::get_sum

1| &Ex2::reset_values

2| &Ex5::v_ex5

 

Ex5::$vftable@Ex4@:

| -8

0| &Ex5::func1

1| &Ex4::func2

 

派生类将每个基类都嵌入了自己,而且每个基类还都保留有自己的虚函数表.但是请注意,第一个基类的虚函数表是被派生类共享的,派生类的虚函数将会被列在基类虚函数表的后面.另外要注意的是,因为Ex5中也有一个和Ex4中的虚函数同名的func1(), 所以根据C++的规则,Ex4虚函数中的func1()函数的指针已经被Ex5的func1()的函数指针给替换掉了.