📄 声明函数指针并实现回调 - jeffreyren的专栏 - csdnblog.htm
字号:
class Bb extends Thread <BR>{ <BR><BR>public static void main(String[] arg)
<BR>{ <BR>Bb b = new Bb(); <BR>for(;;) <BR>b.start(); <BR>} <BR>public void
run() <BR>{ <BR>Syst……</A>
<LI class=listitem>meng_xin:<A title=点击查看《回复:改变对话框的背景色》
href="http://blog.csdn.net/jeffreyren/archive/2001/04/12/6408.aspx#279346">颜色不好</A></LI></UL></SPAN></SPAN><BR><BR></DIV>
<DIV id=main>
<DIV class=Tag>
<SCRIPT language=javascript
src="声明函数指针并实现回调 - jeffreyren的专栏 - CSDNBlog.files/urltag.aspx"></SCRIPT>
<DIV style="CLEAR: both"></DIV></DIV><SPAN class=PreAndNext
id=viewpost.ascx_PreviousAndNextEntriesUp>
<DIV align=center><A
href="http://blog.csdn.net/jeffreyren/archive/2001/02/16/6394.aspx">上一篇: 主页制作动态技术</A> | <A
href="http://blog.csdn.net/jeffreyren/archive/2001/02/01/6392.aspx">下一篇: 得到计算机的主机名和IP地址</A></DIV></SPAN><BR>
<SCRIPT>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</SCRIPT>
<DIV class=post>
<DIV class=postTitle><A
href="http://blog.csdn.net/jeffreyren/archive/2001/02/10/6393.aspx"><IMG
height=13 src="声明函数指针并实现回调 - jeffreyren的专栏 - CSDNBlog.files/authorship.gif"
width=15 border=0> 声明函数指针并实现回调</A> </DIV>
<DIV class=postText>
<TABLE height=400 cellSpacing=0 cellPadding=5 width=608 align=left
bgColor=#ffffff border=0>
<TBODY>
<TR vAlign=top align=left>
<TD class=f1 height=30><B><FONT size=4>声明函数指针并实现回调</FONT><FONT size=3>
</FONT></B></TD>
<TD class=f1 height=30> </TD></TR>
<TR vAlign=top align=middle>
<TD class=f1 colSpan=3 height=10>
<TABLE height=3 cellSpacing=0 cellPadding=0 width=565 border=0>
<TBODY>
<TR>
<TD width=1
background="声明函数指针并实现回调 - jeffreyren的专栏 - CSDNBlog.files/line.gif"></TD></TR></TBODY></TABLE></TD></TR>
<TR vAlign=top align=left>
<TD class=f1 width=6> </TD>
<TD class=f1 id=thetd width=565>
<P>程序员常常需要实现回调。本文将讨论函数指针的基本原则并说明如何使用函数指针实现回调。注意这里针对的是普通的函数,不包括完全依赖于不同语法和语义规则的类成员函数(类成员指针将在另文中讨论)。<BR><BR><!--jcstart--></P>
<P>声明函数指针<BR><BR>
回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。请看下面的例子:<BR><BR>void
f();// 函数原型<BR><BR>上面的语句声明了一个函数,没有输入参数并返回void。那么函数指针的声明方法如下:<BR><BR>void
(*) ();<BR><BR>
让我们来分析一下,左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例中参数是空)。注意本例中还没有创建指针变量-只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小:<BR><BR>//
获得函数指针的大小<BR>unsigned psize = sizeof (void (*) ()); <BR><BR>//
为函数指针声明类型定义<BR>typedef void (*pfv)
();<BR><BR>pfv是一个函数指针,它指向的函数没有输入参数,返回类行为void。使用这个类型定义名可以隐藏复杂的函数指针语法。<BR><BR>指针变量应该有一个变量名:<BR><BR>void
(*p) (); //p是指向某函数的指针<BR><BR>
p是指向某函数的指针,该函数无输入参数,返回值的类型为void。左边圆括弧里星号后的就是指针变量名。有了指针变量便可以赋值,值的内容是署名匹配的函数名和返回类型。例如:<BR><BR>void
func() <BR>{<BR>/* do something */<BR>} <BR>p = func;
<BR><BR>p的赋值可以不同,但一定要是函数的地址,并且署名和返回类型相同。<BR><BR>传递回调函数的地址给调用者<BR><BR>
现在可以将p传递给另一个函数(调用者)- caller(),它将调用p指向的函数,而此函数名是未知的:<BR><BR>void
caller(void(*ptr)())<BR>{<BR>ptr(); /* 调用ptr指向的函数 */ <BR>}<BR>void
func();<BR>int main()<BR>{<BR>p = func; <BR>caller(p); /* 传递函数地址到调用者
*/<BR>}<BR><BR>
如果赋了不同的值给p(不同函数地址),那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。<BR><BR>调用规范<BR><BR>
到目前为止,我们只讨论了函数指针及回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几种调用规范。如在Visual
C++中,可以在函数类型前加_cdecl,_stdcall或者_pascal来表示其调用规范(默认为_cdecl)。C++
Builder也支持_fastcall调用规范。调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右),堆栈清理责任(调用者或者被调用者)以及参数传递机制(堆栈,CPU寄存器等)。<BR><BR>
将调用规范看成是函数类型的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:<BR><BR>//
被调用函数是以int为参数,以int为返回值<BR>__stdcall int callee(int); <BR><BR>//
调用函数以函数指针为参数<BR>void caller( __cdecl int(*ptr)(int)); <BR><BR>//
在p中企图存储被调用函数地址的非法操作<BR>__cdecl int(*p)(int) = callee; //
出错<BR><BR><BR>
指针p和callee()的类型不兼容,因为它们有不同的调用规范。因此不能将被调用者的地址赋值给指针p,尽管两者有相同的返回值和参数列。
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR></P></TD></TR></TBODY></TABLE><BR><BR>
<P id=TBPingURL>Trackback:
http://tb.blog.csdn.net/TrackBack.aspx?PostId=6393</P><BR></DIV>
<DIV class=postFoot>
<SCRIPT src=""></SCRIPT>
[<A title=功能强大的网络收藏夹,一秒钟操作就可以轻松实现保存带来的价值、分享带来的快乐
href="javascript:d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(saveit=window.open('http://wz.csdn.net/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=590,height=300,left=75,top=20,status=no,resizable=yes'));saveit.focus();">收藏到我的网摘</A>]
jeffreyren发表于 2001年02月10日 19:54:00 </DIV></DIV><LINK
href="http://blog.csdn.net/jeffreyren/Services/Pingback.aspx" rel=pingback><!--<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"><rdf:Descriptionrdf:about="http://blog.csdn.net/jeffreyren/archive/2001/02/10/6393.aspx"dc:identifier="http://blog.csdn.net/jeffreyren/archive/2001/02/10/6393.aspx"dc:title="声明函数指针并实现回调"trackback:ping="http://tb.blog.csdn.net/TrackBack.aspx?PostId=6393" /></rdf:RDF>-->
<SCRIPT>function hide(){showComment();}</SCRIPT>
<BR><BR><BR><BR>
<DIV class=post id=csdn_zhaig_ad_yahoo></DIV>
<SCRIPT type=text/javascript>document.write("<img src=http://counter.csdn.net/pv.aspx?id=24 border=0 width=0 height=0>");</SCRIPT>
<SPAN class=PreAndNext id=viewpost.ascx_PreviousAndNextEntriesDown>
<DIV align=center><A
href="http://blog.csdn.net/jeffreyren/archive/2001/02/16/6394.aspx">上一篇: 主页制作动态技术</A> | <A
href="http://blog.csdn.net/jeffreyren/archive/2001/02/01/6392.aspx">下一篇: 得到计算机的主机名和IP地址</A></DIV></SPAN><SPAN
id=Anthem_Comments.ascx_ltlComments__><SPAN id=Comments.ascx_ltlComments><BR>
<DIV id=comments>
<H3></H3>没有评论。 </DIV></SPAN></SPAN>
<SCRIPT language=javascript>
ad_width=468;
ad_height=60;
adcss=2;
unionuser=19;
ad_type='j';
count=5;
</SCRIPT>
<DIV>
<SCRIPT language=javascript
src="声明函数指针并实现回调 - jeffreyren的专栏 - CSDNBlog.files/showads.js"
type=text/javascript></SCRIPT>
<SCRIPT language=javascript
src="声明函数指针并实现回调 - jeffreyren的专栏 - CSDNBlog.files/showgm.js"
type=text/javascript></SCRIPT>
</DIV>
<DIV class=CommentForm id=commentform>
<H3>发表评论 </H3>
<DIV id=Anthem_PostComment.ascx_CommentUpdatePanel__>
<DIV id=PostComment.ascx_CommentUpdatePanel>
<TABLE class=CommentForm>
<TBODY>
<TR>
<TD width=69 height=0></TD>
<TD></TD></TR>
<TR>
<TD width=70>大名:</TD>
<TD align=left><INPUT id=PostComment.ascx_tbName style="WIDTH: 300px"
disabled maxLength=32 size=40 name=PostComment.ascx:tbName> <SPAN
id=PostComment.ascx_RequiredFieldValidator2
style="DISPLAY: none; COLOR: red" initialvalue=""
evaluationfunction="RequiredFieldValidatorEvaluateIsValid"
display="Dynamic" errormessage="<br>请输入尊姓大名"
controltovalidate="PostComment.ascx_tbName"><BR>请输入尊姓大名</SPAN> </TD></TR>
<TR>
<TD width=70>网址:</TD>
<TD align=left><INPUT id=PostComment.ascx_tbUrl style="WIDTH: 300px"
disabled maxLength=256 size=40 name=PostComment.ascx:tbUrl> </TD></TR>
<TR>
<TD colSpan=3>评论 <SPAN id=PostComment.ascx_RequiredFieldValidator3
style="DISPLAY: none; COLOR: red" initialvalue=""
evaluationfunction="RequiredFieldValidatorEvaluateIsValid"
display="Dynamic" errormessage="<br>请输入评论"
controltovalidate="PostComment.ascx_tbComment"><BR>请输入评论</SPAN> <BR><TEXTAREA id=PostComment.ascx_tbComment style="WIDTH: 381px; HEIGHT: 193px" disabled name=PostComment.ascx:tbComment rows=10 cols=50></TEXTAREA>
</TD></TR>
<TR>
<TD colSpan=3><SPAN
id=Anthem_PostComment.ascx_btnSubmit__></SPAN> </TD></TR>
<TR>
<TD colSpan=3><SPAN id=PostComment.ascx_Message
style="COLOR: red">当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击<A
href="http://passport.csdn.net/member/UserLogin.aspx?from=http://blog.csdn.net/jeffreyren/archive/2001/02/10/6393.aspx">登录</A></SPAN>
</TD></TR></TBODY></TABLE></DIV></DIV></DIV></DIV>
<P id=footer>Powered by: <BR><A id=Footer1_Hyperlink2
href="http://scottwater.com/blog" name=Hyperlink1><IMG
src="声明函数指针并实现回调 - jeffreyren的专栏 - CSDNBlog.files/100x30_Logo.gif" border=0></A>
<A id=Footer1_Hyperlink3 href="http://asp.net/" name=Hyperlink1><IMG
src="声明函数指针并实现回调 - jeffreyren的专栏 - CSDNBlog.files/PoweredByAsp.Net.gif"
border=0></A> <BR>Copyright © jeffreyren </P>
<SCRIPT src="声明函数指针并实现回调 - jeffreyren的专栏 - CSDNBlog.files/counter.js"></SCRIPT>
<SCRIPT type=text/javascript>
<!--
var Page_Validators = new Array(document.getElementById("PostComment.ascx_RequiredFieldValidator2"), document.getElementById("PostComment.ascx_RequiredFieldValidator3"));
// -->
</SCRIPT>
<INPUT id=__EVENTVALIDATION type=hidden
value=/wEWBAL+raDpAgKqtOi0AwLAsuLbDAKi687YCRVBuzeSL2QMny3dHQdvj+GkEVhY
name=__EVENTVALIDATION>
<SCRIPT type=text/javascript>
<!--
var Page_ValidationActive = false;
if (typeof(ValidatorOnLoad) == "function") {
ValidatorOnLoad();
}
function ValidatorOnSubmit() {
if (Page_ValidationActive) {
return ValidatorCommonOnSubmit();
}
else {
return true;
}
}
// -->
</SCRIPT>
</FORM>
<SCRIPT language=javascript type=text/javascript>
<!--
try
{
hide();
}
catch(e){}
//-->
</SCRIPT>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -