欢迎来到天天文库
浏览记录
ID:14406303
大小:341.16 KB
页数:13页
时间:2018-07-28
《从汇编看c 的虚拟继承以及其内存布局》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、从汇编看c++的虚拟继承以及其内存布局先看第一种最简单的情形,所有类中没有任何虚函数的菱形继承。 下面是c++源码:classTop{//虚基类public: inti; Top(intii){ i=ii; }};classLeft:publicvirtualTop{public: intj; Left(intjj,intii):Top(ii){ j=jj; }};classRight:publicvirtualTop{public: intk; Right(intkk
2、,intii):Top(ii){ k=kk; }};classBottom:publicLeft,publicRight{public: intl; Bottom(intll,intjj,intkk,intii):Top(ii),Left(jj,ii),Right(kk,ii){ l=ll; }};intmain(){ Bottomb(1,2,3,4); Bottom*bp=&b; //访问自身成员变量 b.l=1; bp->l=2; //访问父类Left的成员变
3、量 Left*lp=bp; b.j=1; bp->j=2; lp->j=3; //访问父类Right的成员变量 Right*rp=bp; b.k=1; bp->k=2; rp->k=3; //访问虚基类Top的成员变量 Top*tp=bp; b.i=1; bp->i=2; tp->i=3; }; 让我们来看看,汇编代码里面是怎样的情形,先看main函数里面的汇编码:;33 :intmain(){ push ebp mov ebp,esp sub
4、 esp,48 ;为对象程序所需变量预留空间,其中对象b只栈24byte;34 : Bottomb(1,2,3,4); push 1;压入标志1,作为判断是否调用虚基类构造函数的依据1表示调用,0表示不调用 push 4;压栈4,为对象b的构造函数传递参数 push 3;压栈3,为对象b的构造函数传递参数 push 2;压栈2,为对象b的构造函数传递参数 push 1;压栈1,为对象b的构造函数传递参数 lea ecx,DWORDPT
5、R_b$[ebp];获取对象b的首地址,传给寄存器ecx,作为隐含参数传递给对象b的构造函数 call ??0Bottom@@QAE@HHHH@Z ;调用对象b的构造函数;35 : Bottom*bp=&b; lea eax,DWORDPTR_b$[ebp];将对象b的首地址给寄存器eax mov DWORDPTR_bp$[ebp],eax;将对象b的首地址给指针变量bp;36 : ;37 : b.l=1; mov DWORDPTR_b$[ebp+16]
6、,1;将1写入偏移对象首地址16字节处内存,即为对象b的成员变量l赋值1;38 : bp->l=2; mov ecx,DWORDPTR_bp$[ebp];将对象b的首地址给寄存器ecx mov DWORDPTR[ecx+16],2;将2写入偏移对象首地址16字节处内存,即为对象b的成员变量l赋值2 ;可以看到,无论是用对象本身,还是对象指针访问对象b的成员变量 ;其成员变量的偏移量都在编译期固定了
7、,为16字节 ;且两种方式访问没有差别;39 : ;40 : Left*lp=bp; mov edx,DWORDPTR_bp$[ebp];将对象b的首地址给寄存器edx mov DWORDPTR_lp$[ebp],edx;将对象b的首地址给对象指针lp,此时lp指向父对象Left的首地址 ;从下面的内存布局图可以看到,父对象Left的首地址和Bottom一样;41 : b.j=
8、1; mov DWORDPTR_b$[ebp+4],1;将1赋给偏移对象b首地址4byte处内存,即为 ;继承来的成员变量j赋值1;42 : bp->j=2; mov eax,DWORDPTR_
此文档下载收益归作者所有