📄 csdn_文档中心_c++类机制的实现细节.htm
字号:
<TD align=middle height=5></TD>
<TD align=middle width=500></TD></TR>
<TR>
<TD align=middle bgColor=#003399 height=10><FONT
color=#ffffff>标题</FONT></TD>
<TD><B> C++类机制的实现细节</B> nightsuns(原作)
</TD></TR>
<TR>
<TD align=middle height=5></TD>
<TD align=middle width=500></TD></TR>
<TR>
<TD align=middle bgColor=#003399><FONT color=#ffffff>关键字</FONT></TD>
<TD width=500> 类机制 实现细节</TD></TR>
<TR>
<TD align=middle height=5></TD>
<TD align=middle width=500></TD></TR></TBODY></TABLE><!--文章说明信息结束//-->
<TABLE border=0 width=600>
<TBODY>
<TR>
<TD align=left><BR>
<P><SPAN id=yuyuzi>为了搞清楚VC中类的实现专门写了一个最简单的类,用来观察它的实现过程,代码如下:<BR>//
test.cpp : Defines the entry point for the console
application.<BR>//<BR><BR>#include "stdafx.h"<BR>#include
"CTest.h"<BR><BR>int main(int argc, char* argv[])<BR>{<BR>CTest
aTest;<BR>aTest.a(1,2);<BR>return 0;<BR>}<BR><BR>// CTest.h:
interface for the CTest
class.<BR>//<BR>//////////////////////////////////////////////////////////////////////<BR><BR>#if
!defined(AFX_CTEST_H__2CCCDCFC_6C3A_48BC_9CD0_E7A8E63431D9__INCLUDED_)<BR>#define
AFX_CTEST_H__2CCCDCFC_6C3A_48BC_9CD0_E7A8E63431D9__INCLUDED_<BR><BR>#if
_MSC_VER > 1000<BR>#pragma once<BR>#endif // _MSC_VER >
1000<BR><BR>class CTest <BR>{<BR>public:<BR>CTest();<BR>virtual
~CTest();<BR><BR>public:<BR>void b();<BR>void a(int one,int
two);<BR>};<BR><BR>#endif //
!defined(AFX_CTEST_H__2CCCDCFC_6C3A_48BC_9CD0_E7A8E63431D9__INCLUDED_)<BR><BR><BR>//
CTest.cpp: implementation of the CTest
class.<BR>//<BR>//////////////////////////////////////////////////////////////////////<BR><BR>#include
"stdafx.h"<BR>#include
"CTest.h"<BR><BR>//////////////////////////////////////////////////////////////////////<BR>//
Construction/Destruction<BR>//////////////////////////////////////////////////////////////////////<BR><BR>CTest::CTest()<BR>{<BR><BR>}<BR><BR>CTest::~CTest()<BR>{<BR><BR>}<BR><BR>void
CTest::b()<BR>{<BR>printf("b is be called by a");<BR>}<BR><BR>void
CTest::a(int one,int two)<BR>{<BR>printf("call
b");<BR>b();<BR>}<BR><BR><BR><BR><BR>下面是相应的反汇编代码:<BR>---
D:\myown\test\test.cpp -----------------------------------------------------------------------------------------------<BR>1: //
test.cpp : Defines the entry point for the console
application.<BR>2: //<BR>3:<BR>4: #include
"stdafx.h"<BR>5: #include "CTest.h"<BR>6:<BR>7: int main(int argc,
char* argv[])<BR>8: {<BR>00401050 push ebp<BR>00401051 mov
ebp,esp<BR>00401053 push 0FFh<BR>00401055 push offset
__ehhandler$_main (00410c89)<BR>0040105A mov
eax,fs:[00000000]<BR>00401060 push eax<BR>00401061 mov
dword ptr fs:[0],esp<BR>00401068 sub esp,48h<BR>0040106B
push ebx<BR>0040106C push esi<BR>0040106D
push edi<BR>0040106E lea edi,[ebp-54h]<BR>00401071 mov
ecx,12h<BR>00401076 mov eax,0CCCCCCCCh<BR>0040107B rep
stos dword ptr [edi]<BR><BR>9: CTest aTest;<BR>0040107D lea
ecx,[ebp-10h] //这是用来保存aTest的this指针,因为是局部变量所以是保存在[ebp-10h]中<BR>00401080
call @ILT+30(CTest::CTest)
(00401023) //调用aTest的构造函数,由编译器自动产生的CALL<BR>00401085 mov dword
ptr [ebp-4],0<BR><BR>10: aTest.a(1,2);<BR>0040108C
push 2<BR>0040108E push 1<BR>00401090 lea
ecx,[ebp-10h] //把aTest的this指针用ecx进行传递<BR>00401093
call @ILT+5(CTest::a) (0040100a) <BR>11: return
0;<BR>00401098 mov dword ptr [ebp-14h],0<BR>0040109F mov
dword ptr [ebp-4],0FFFFFFFFh<BR>004010A6 lea
ecx,[ebp-10h] //同样是this指针<BR>004010A9
call @ILT+25(CTest::~CTest)
(0040101e) //aTest的生存周期到了,自动调用析构函数,同样是由编译器分析之后自加上去<BR>004010AE
mov eax,dword ptr [ebp-14h]<BR>12: }<BR>004010B1 mov
ecx,dword ptr [ebp-0Ch]<BR>004010B4 mov dword ptr
fs:[0],ecx<BR>004010BB pop edi<BR>004010BC pop
esi<BR>004010BD pop ebx<BR>004010BE add
esp,54h<BR>004010C1 cmp ebp,esp<BR>004010C3 call __chkesp
(00401670)<BR>004010C8 mov esp,ebp<BR>004010CA pop
ebp<BR>004010CB
ret<BR><BR>下面再来分析一下VC中对函数的调用:<BR>可以看到上面有对三个函数的调用分别为:<BR>00401080
call @ILT+30(CTest::CTest) (00401023)<BR>00401093
call @ILT+5(CTest::a) (0040100a)<BR>004010A9
call @ILT+25(CTest::~CTest)
(0040101e)<BR><BR>可以看到他们都跳到了以@ILT为基的一个地址去了,那么跳过去之后可以看到:<BR>@ILT+0(??_GCTest@@UAEPAXI@Z):<BR>00401005
jmp CTest::`scalar deleting destructor'
(00401130)<BR>@ILT+5(?a@CTest@@QAEXHH@Z):<BR>0040100A jmp
CTest::a (00401230)<BR>@ILT+10(_main):<BR>0040100F jmp main
(00401050)<BR>@ILT+15(?b@CTest@@QAEXXZ):<BR>00401014 jmp
CTest::b (004011e0)<BR>@ILT+20(??_GCTest@@UAEPAXI@Z):<BR>00401019
jmp CTest::`scalar deleting destructor'
(00401130)<BR>@ILT+25(??1CTest@@UAE@XZ):<BR>0040101E jmp
CTest::~CTest (004011a0)<BR>@ILT+30(??0CTest@@QAE@XZ):<BR>00401023
jmp CTest::CTest
(004010f0)<BR><BR>这个@ILT其实就是一个静态的表,它记录了一些函数的入口然后跳过去,每个跳转jmp占一个字节,然后就是一个四字节的内存地址,所以加起为五个字节,这样就实现了类的机制。<BR><BR>下面再来分析一下,类的成员函数调用另一成员函数的情况:<BR><BR>27:
void CTest::a(int one,int two)<BR>28: {<BR>00401230
push ebp<BR>00401231 mov ebp,esp<BR>00401233 sub
esp,44h<BR>00401236 push ebx<BR>00401237
push esi<BR>00401238 push edi<BR>00401239
push ecx<BR>0040123A lea edi,[ebp-44h]<BR>0040123D mov
ecx,11h<BR>00401242 mov eax,0CCCCCCCCh<BR>00401247 rep
stos dword ptr [edi]<BR>00401249 pop ecx<BR>0040124A mov
dword ptr [ebp-4],ecx<BR>29: printf("call b");<BR>0040124D
push offset string "call b" (00422038)<BR>00401252
call printf (00401830)<BR>00401257 add esp,4<BR>30:
b();<BR>0040125A mov ecx,dword ptr [ebp-4]
//不要想这里的[ebp-4]肯定是this指针,<BR>0040125D call @ILT+15(CTest::b)
(00401014) // 又是@ILT静态表格<BR>31: }<BR>00401262 pop
edi<BR>00401263 pop esi<BR>00401264 pop ebx<BR>00401265
add esp,44h<BR>00401268 cmp ebp,esp<BR>0040126A
call __chkesp (00401670)<BR>0040126F mov
esp,ebp<BR>00401271 pop ebp<BR>00401272 ret
8 //由于是STDCALLR所以栈是由程序自己来平衡的<BR></SPAN></P><BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR>
<TABLE align=center bgColor=#006699 border=0 cellPadding=0 cellSpacing=0
width=770>
<TBODY>
<TR bgColor=#006699>
<TD align=middle bgColor=#006699 id=white><FONT
color=#ffffff>对该文的评论</FONT></TD>
<TD align=middle>
<SCRIPT src="CSDN_文档中心_C++类机制的实现细节.files/readnum.htm"></SCRIPT>
</TD></TR></TBODY></TABLE><BR>
<DIV align=center>
<TABLE align=center bgColor=#cccccc border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TH bgColor=#006699 id=white><FONT
color=#ffffff>我要评论</FONT></TH></TR></TBODY></TABLE></DIV>
<SCRIPT language=javascript>
<!--
function isEmpty(s)
{
return ((s == null) || (s.length == 0))
}
function fubmitok()
{
if (isEmpty(document.add_critique.Critique_Content.value))
{
alert('评论不能为空!!!!') ;
return false;
}
document.add_critique.submit();
}
//-->
</SCRIPT>
<DIV align=center>
<TABLE border=0 width=770>
<TBODY>
<TR>
<TD>
<FORM action=Critique_Sql.asp method=post name=add_critique><INPUT
name=Critique_State type=hidden value=add> 评论人:xyj0323
评论:<BR> <TEXTAREA cols=104 name=Critique_Content rows=8></TEXTAREA><BR> <INPUT name=ubmit onclick=javascript:fubmitok(); type=button value=发表评论>
<INPUT name=Topic_id type=hidden value=27050> <INPUT name=From type=hidden
value=/Develop/Build_Article.asp?id=27050>
</FORM></TD></TR></TBODY></TABLE></DIV><BR>
<HR noShade SIZE=1 width=770>
<TABLE border=0 cellPadding=0 cellSpacing=0 width=500>
<TBODY>
<TR align=middle>
<TD height=10 vAlign=bottom><A
href="http://www.csdn.net/intro/intro.asp?id=2">网站简介</A> - <A
href="http://www.csdn.net/intro/intro.asp?id=5">广告服务</A> - <A
href="http://www.csdn.net/map/map.shtm">网站地图</A> - <A
href="http://www.csdn.net/help/help.asp">帮助信息</A> - <A
href="http://www.csdn.net/intro/intro.asp?id=2">联系方式</A> - <A
href="http://www.csdn.net/english">English</A> </TD>
<TD align=middle rowSpan=3><A
href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010"><IMG
border=0 height=48 src="CSDN_文档中心_C++类机制的实现细节.files/biaoshi.gif"
width=40></A></TD></TR>
<TR align=middle>
<TD vAlign=top>百联美达美公司 版权所有 京ICP证020026号</TD></TR>
<TR align=middle>
<TD vAlign=top><FONT face=Verdana>Copyright © CSDN.net, Inc. All rights
reserved</FONT></TD></TR>
<TR>
<TD height=15></TD>
<TD></TD></TR></TBODY></TABLE></DIV>
<DIV></DIV><!--内容结束//--><!--结束//--></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -