vs2008下C++对象内存布局(2):简单继承

本文详细探讨了在VS2008环境下C++中父类与子类的内存布局特性,包括数据成员的合并存储方式及函数调用机制,并通过实例展示了变量覆盖和函数覆盖的具体实现。

快乐虾

http://blog.youkuaiyun.com/lights_joy/

lights@hb165.com

 

本文适用于

Xp sp3

Vs2008

 

欢迎转载,但请保留作者信息

 

这次我们添加一个子类,父类和子类均不带虚函数:

class CParent

{

public:

     int parent_a;

     int parent_b;

 

public:

     void parent_f1()

     {

         parent_a = 0x10;

     }

     void parent_f2()

     {

         parent_b = 0x20;

     }

};

 

class CChild : public CParent

{

public:

     int child_a;

     int child_b;

 

public:

     void child_f1()

     {

         child_a = 0x30;

     }

     void child_f2()

     {

         child_b = 0x40;

     }

};

1.1.1   内存布局

先给这些成员变量赋几个值:

     child.parent_a = 1;

0041138E C7 05 50 71 41 00 01 00 00 00 mov         dword ptr [child (417150h)],1

     child.parent_b = 2;

00411398 C7 05 54 71 41 00 02 00 00 00 mov         dword ptr [child+4 (417154h)],2

     child.child_a = 3;

004113A2 C7 05 58 71 41 00 03 00 00 00 mov         dword ptr [child+8 (417158h)],3

     child.child_b = 4;

004113AC C7 05 5C 71 41 00 04 00 00 00 mov         dword ptr [child+0Ch (41715Ch)],4

观察&child所指的内存区内容:

0x00417150  01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00  ................

很明显,VS将父类和子类的数据成员合并到同一块内存区域,但是同样没有往里面加额外的东西,&child指针将指向第一个成员parent_a

1.1.2   函数调用

观察函数调用:

     child.parent_f1();

00411840 B9 50 71 41 00   mov         ecx,offset child (417150h)

00411845 E8 78 F9 FF FF   call        CParent::parent_f1 (4111C2h)

     child.child_f1();

0041184A B9 50 71 41 00   mov         ecx,offset child (417150h)

0041184F E8 64 F9 FF FF   call        CChild::child_f1 (4111B8h)

和简单父类的函数调用没什么两样。用ECX传递this指针。

1.1.3   变量覆盖

在子类里添加两个和父类同名的成员变量:

class CChild : public CParent

{

public:

     int child_a;

     int child_b;

     int parent_a;

     int parent_b;

………

再执行前面的赋值语句:

     child.parent_a = 1;

0041180E C7 05 04 75 41 00 01 00 00 00 mov         dword ptr [child+10h (417504h)],1

     child.parent_b = 2;

00411818 C7 05 08 75 41 00 02 00 00 00 mov         dword ptr [child+14h (417508h)],2

     child.child_a = 3;

00411822 C7 05 FC 74 41 00 03 00 00 00 mov         dword ptr [child+8 (4174FCh)],3

     child.child_b = 4;

0041182C C7 05 00 75 41 00 04 00 00 00 mov         dword ptr [child+0Ch (417500h)],4

可以发现赋值时使用的偏移量发生了变化,观察&child所在的内存区:

0x004174F4  00 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00  ................

0x00417504  01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00  ................

可以看到合并后的内存有6个整数,且对child.parent_a的赋值其实是对子类的成员进行赋值。

而当我们用下面的赋值语句时:

     pparent = &child;

00412E44 C7 05 E4 74 41 00 F4 74 41 00 mov         dword ptr [pparent (4174E4h)],offset child (4174F4h)

     pparent->parent_a = 1;

00412E4E A1 E4 74 41 00   mov         eax,dword ptr [pparent (4174E4h)]

00412E53 C7 00 01 00 00 00 mov         dword ptr [eax],1

     pparent->parent_b = 2;

00412E59 A1 E4 74 41 00   mov         eax,dword ptr [pparent (4174E4h)]

00412E5E C7 40 04 02 00 00 00 mov         dword ptr [eax+4],2

从偏移量就可以看出它是对父类的成员进行赋值。

1.1.4   函数覆盖

在子类里面添加一个和父类同名的函数,再进行函数调用:

     pchild = &child;

00412E26 C7 05 F0 74 41 00 F4 74 41 00 mov         dword ptr [pchild (4174F0h)],offset child (4174F4h)

     pchild->parent_f1();

00412E30 8B 0D F0 74 41 00 mov         ecx,dword ptr [pchild (4174F0h)]

00412E36 E8 9B E3 FF FF   call        CChild::parent_f1 (4111D6h)

 

     pparent = &child;

00412E3B C7 05 E4 74 41 00 F4 74 41 00 mov         dword ptr [pparent (4174E4h)],offset child (4174F4h)

     pparent->parent_f1();

00412E45 8B 0D E4 74 41 00 mov         ecx,dword ptr [pparent (4174E4h)]

00412E4B E8 72 E3 FF FF   call        CParent::parent_f1 (4111C2h)

从反汇编的结果可以明显看出使用父类指针和使用子类指针调用同名函数时的差异。

 

 

 

 

2       参考资料

vs2008C++对象内存布局(1(2009-9-9)

 

 

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值