#include <iostream>
using namespace std;
class A
{
public:
long a;
};
class B: public A
{
public:
long b;
};
void set(A * data, int idx)
{
d[idx].a = 2;
}
int _tmain(int argc, _TCHAR* argv[])
{
B data[4];
for(int i=0; i<4; i++)
{
data[i].a = 1;
data[i].b = 1;
set(data, i);
}
for(int i=0; i<4; i++)
{
cout<<data[i].a<<data[i].b;
}
system("pause");
return 0;
}
问这个的输出: 答案应该是22221111.
注意:void set(A * data, int idx); 这个函数地参数,是A类的一个指针。操作时按A类的内存模式操作。
对于本题, 在B类的对象中有A类的子对象。内存分配图应该是下面这样子:
a | b |
a | b |
a | b |
a | b |
当调用set函数时, 传给set的参数data是数组首元素的地址, idx是数组下标的索引。但是对data这个地址的操作是按A类对象的内存模式操作的。看反汇编代码:
void set(A * data, int idx)
{
004113C0 push ebp
004113C1 mov ebp,esp
004113C3 sub esp,0C0h
004113C9 push ebx
004113CA push esi
004113CB push edi
004113CC lea edi,[ebp-0C0h]
004113D2 mov ecx,30h
004113D7 mov eax,0CCCCCCCCh
004113DC rep stos dword ptr es:[edi] //以上是为set函数的栈参数和环境等信息进行的准备工作,不用管
d[idx].a = 2;
004113DE mov eax,dword ptr [idx] //这里得到下标值
004113E1 mov ecx,dword ptr [data] //ecx存放data的地址
004113E4 mov dword ptr [ecx+eax*4],2 //关键的部位, 每次操作的是A类对象的内存模式, 即data首地址 + 索引值 * 4(long类型变量占用的字节数)
}
这样很明显:
当idx=0, data[idx] 的地址就是 data[0],即 0x0012FF44,
当idx=1, data[idx]的地址就是data[1]即0x0012FF4c,
内存中的内容如下:0x0012FF44 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 cc cc cc cc cc cc
这样操作下来, 内存中连续的内存空间被设置成如下:
2 | 2 |
2 | 2 |
1 | 1 |
1 | 1 |
所以, 得出的输出结果是22221111.