⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 什么是回调函数那_编程论坛.htm

📁 最全的介绍C语言结构体的使用方法和使用技巧!
💻 HTM
📖 第 1 页 / 共 4 页
字号:
style="FONT-WEIGHT: bold; COLOR: red">5</FONT> 楼</A> </DIV>&nbsp;<A 
href="mailto:zy-841120@163.com"><IMG alt=点击这里发送电子邮件给luckbird 
src="什么是回调函数那_编程论坛.files/email.gif" align=middle border=0></A> </DIV>
<DIV 
style="TEXT-INDENT: 0px; LINE-HEIGHT: 22px; PADDING-TOP: 5px; HEIGHT: 22px"><B></B></DIV>
<DIV 
style="PADDING-RIGHT: 0px; MARGIN-TOP: 10px; FONT-SIZE: 9pt; OVERFLOW-X: hidden; WIDTH: 97%; WORD-BREAK: break-all; LINE-HEIGHT: normal; HEIGHT: 160px; WORD-WRAP: break-word">还是不太理解 呼唤达人给详细点的解释</DIV></DIV></DIV>
<DIV class=postbottom1>
<DIV class=postuserinfo style="HEIGHT: 24px">
<DIV style="FLOAT: left"><IMG style="MARGIN: 4px" 
src="什么是回调函数那_编程论坛.files/ip.gif"></DIV>2006-3-25 19:38:00</DIV>
<DIV class=postie 
style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; TEXT-INDENT: 10px; PADDING-TOP: 0px; HEIGHT: 24px">
<DIV style="FLOAT: right; MARGIN-RIGHT: 5px"><A 
href="http://bbs.bc-cn.net/dispbbs.asp?boardID=55&amp;ID=52123#top"><IMG 
style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 3px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" 
alt="" src="什么是回调函数那_编程论坛.files/p_up.gif"></A> </DIV>
<DIV></DIV></DIV></DIV><A name=77349></A><A id=l6 name=6></A>
<DIV class=postlary2>
<DIV class=postuserinfo>
<DIV 
style="FILTER: glow(color='#A6BA98',strength='2'); FLOAT: left; MARGIN: 13px 0px 0px 2px; WIDTH: 123px; LINE-HEIGHT: 23px; HEIGHT: 27px"><FONT 
color=#000066><B>幽园香客</B></FONT></DIV>
<DIV 
style="FLOAT: left; MARGIN: 13px 0px 0px; WIDTH: 23px; TEXT-INDENT: 0px; LINE-HEIGHT: 23px; HEIGHT: 27px"><IMG 
alt=帅哥哟,离线,有人找我吗? src="什么是回调函数那_编程论坛.files/ofMale.gif"> </DIV>
<DIV style="MARGIN: 0px 0px 0px 24px"><IMG height=90 
src="什么是回调函数那_编程论坛.files/image2.gif" width=82><BR><IMG 
style="MARGIN: 1px 0px 2px" 
src="什么是回调函数那_编程论坛.files/level1.gif"><BR>来自:NUA<BR>等级:论坛游民<BR>文章:173<BR>积分:2761<BR>注册:2006年2月27日<BR></DIV></DIV>
<DIV class=postie>
<DIV class=dispbbs_hr>
<DIV style="FLOAT: right"><A title=下一楼 onclick=xl(7) 
href="http://bbs.bc-cn.net/dispbbs.asp?boardID=55&amp;ID=52123#7">第 <FONT 
style="FONT-WEIGHT: bold; COLOR: red">6</FONT> 楼</A> </DIV>&nbsp;<A 
href="mailto:youyuanxiangke@yahoo.com"><IMG alt=点击这里发送电子邮件给幽园香客 
src="什么是回调函数那_编程论坛.files/email.gif" align=middle border=0></A> </DIV>
<DIV 
style="TEXT-INDENT: 0px; LINE-HEIGHT: 22px; PADDING-TOP: 5px; HEIGHT: 22px"><B></B></DIV>
<DIV 
style="PADDING-RIGHT: 0px; MARGIN-TOP: 10px; FONT-SIZE: 9pt; OVERFLOW-X: hidden; WIDTH: 97%; WORD-BREAK: break-all; LINE-HEIGHT: normal; HEIGHT: 160px; WORD-WRAP: break-word">转贴:<BR><BR>
<P>先泛后精,先浅后深”的道理可是知易行难,所以常常会给技术上的小细节纠缠着,搞得晕晕乎,其中“回调函数”就是其中之一了,虽然回用,但是老是不明白其中的含义,众多的书本也说得隐晦不清。直到不久前看到一篇文章才总算比较清晰了解。</P><BR>
<P>概括起来,回调机制包括两部分:服务执行者和服务方式制定者。<BR>1. 
服务执行者先制定服务规范;<BR>2.服务方式制定者然后按照规范制定服务方式;<BR>3.然后执行者按照这个方式提供服务。<BR>回调函数的方式是把函数指针的作为参数传递进去,所以规范就是约定函数的参数类型,个数。</P><BR>
<P>这篇文章如下:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;调用(calling)机制从汇编时代起已经大量使用:准备一段现成的代码,调用者可以随时跳转至此段代码的起始地址,执行完后再返回跳转时的后续地址。 
CPU为此准备了现成的调用指令,调用时可以压栈保护现场,调用结束后从堆栈中弹出现场地址,以便自动返回。借堆栈保护现场真是一项绝妙的发明,它使调用<BR>者和被调者可以互不相识,于是才有了后来的函数和构件,使吾辈编程者如此轻松愉快。若评选对人类影响最大之发明,在火与车轮之后,笔者当推压栈调用。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
话虽这样说,此调用机制并非完美。回调函数就是一例。函数之类本是为调用者准备的美餐,其烹制者应对食客了如指掌,但实情并非如此。例如,写一个快速排序<BR>函数供他人调用,其中必包含比较大小。麻烦来了:此时并不知要比较的是何类数据--整<BR>数、浮点数、字符串?于是只好为每类数据制作一个不同的排序函数。更<BR>通行的办法是在函数参数中列一个回调函数地址,并通知调用者:君需自己准备一个比较函数,其中包含两个指针类参数,函数要比较此二指针所指数据之大小,并<BR>由函数返回值说明比较结果。排序函数借此调用者提供的函数来比较大小,借指针传递参数,可以全然不管所比较的数据类型。被调用者回头调用调用者的函数(够<BR>咬嘴的),故称其为回调(callback)。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;回调函数使程序结构乱了许多。Windows 
API 
函数集中有不少回调函数,尽管有详尽说明,仍使初学者一头雾水。恐怕这也是无奈之举。无论何种事物,能以树形结构单向描述毕竟让人舒服些。如果某家族中孙<BR>辈又是某祖辈的祖辈,恐怕无人能理清其中的头绪。但数据处理之复杂往往需要构成网状结构,非简单的客户/服务器关系能穷尽。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
Windows 系统还包含着另一种更为广泛的回调机制,即消息机制。消息本是 Windows 
的基本控制手段,乍看与函数调用无关,其实是一种变相的函数调用。发送消息的目的是通知收方运行一段预先准备好的代码,相当于调用一个函数。消息所附带的 WParam 
和 LParam 相当于函数的参数,只不过比普通参数更通用一些。应用程序可以主动发送消息,更多情况下是坐等 Windows 
发送消息。一旦消息进入所属消息队列,便检感兴趣的那些,跳转去执行相应的消息处理代码。操作系统本是为应用程序服务,由应用程序来调用。而应用程序一旦<BR>启动,却要反过来等待操作系统的调用。这分明也是一种回调,或者说是一种广义回调。其实,应用程序之间也可以形成这种回调。假如进程<BR>B 
收到进程 A 发来的消息,启动了一段代码,其中又向进程 
A<BR>发送消息,这就形成了回调。这种回调比较隐蔽,弄不好会搞成递归调用,若缺少终止条件,将会循环不已,直至把程序搞垮。若是故意编写成此递归调用,并设好<BR>终止条件,倒是很有意思。但这种程序结构太隐蔽,除非十分必要,还是不用为好。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
利用消息也可以构成狭义回调。上面所举排序函数一例,可以把回调函数地址换成窗口handle。如此,当需要比较数据大小时,不是去调用回调函数,而是借 API 函数 
SendMessage 
向<BR>指定窗口发送消息。收到消息方负责比较数据大小,把比较结果通过消息本身的返回值传给消息发送方。所实现的功能与回调函数并无不同。当然,此例中改为消<BR>息纯属画蛇添脚,反倒把程序搞得很慢。但其他情况下并非总是如此,特别是需要异步调用时,发送消息是一种不错的选择。假如回调函数中包含文件处理之类的低<BR>速处理,调用方等不得,需要把同步调用改为异步调用,去启动一个单独的线程,然后马上执行后续代码,其余的事让线程慢慢去做。一个替代办法是借 
API 函数 
PostMessage发送一个异步消息,然后立即执行后续代码。这要比自己搞个线程省事许多,而且更安全。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
如今我们是活在一个 object 时代。只要与编程有关,无论何事都离不开 object。但 object 
并未消除回调,反而把它发扬光大,弄得到处都是,只不过大都以事件(event)的身份出现,镶嵌在某个结构之中,显得更正统,更容易被人接受。应用程序 
要使用某个构件,总要先弄清构件的属性、方法和事件,然后给构件属性赋值,在适当的时候调用适当的构件方法,还要给事件编写处理例程,以备构件代码来调<BR>用。何谓事件?它不过是一个指向事件例程的地址,与回调函数地址没什么区别。<BR>&nbsp;&nbsp;&nbsp;&nbsp;不过,此种回调方式比传统回调函数要高明许多。首先,它把让人不太舒服的回调函数变成一种自然而然的处理例程,使编程者顿觉气顺。再者,地址是一个危险的<BR>东西,用好了可使程序加速,用不好处处是陷阱,程序随时都会崩溃。现代编程方式总是想法把地址隐藏起来(隐藏比较彻底的如 
VB 和 
Java),其代价是降低了程序效率。事件例程使编程者无需直接操作地址,但并不会使程序减速。更妙的是,此一改变,本是有损程序结构之奇技怪巧变成一种<BR>崭新设计理念,不仅免去被人抨击,而且逼得吾等凡人净手更衣,细细研读,仰慕至今。只是偶然静心思虑,发觉不过一瓶旧酒而已,故引得此番议论,让<ST1:PERSONNAME 
w:st="on" productid="诸">诸</ST1:PERSONNAME>君见笑 了。 
事件驱动程序设计是围绕着消息基础形成的,发生一个事件,伴随着一大堆的消息。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
我理解“回调机制”是window 在执行某个API函数的过程中,调用指定的一个函数。我们可以模拟一下:<BR>假设 ms 
提供一个函数叫做&nbsp;&nbsp;EnumFont 
,该函数是得到所有的字体,假设它的实现是<BR>EnumFont()<BR>{<BR>&nbsp;&nbsp;while ( (f 
=FindNextFont()) 
!=NULL)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
printf("fontname: " + 
f.name);<BR>&nbsp;&nbsp;}<BR>}<BR>这样就循环显示出所有的字体名称。但是,开发者可能对字体信息另有用处,那么如何才能让开发者能使用这些信息呢,于是做改进:<BR>EnumFont( 
void*&nbsp;&nbsp;userFunc )<BR>{<BR>&nbsp;&nbsp;while ( (f =FindNextFont()) 
!=NULL)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
printf("fontname: " + f.name);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( 
userFunc!=NULL)&nbsp;&nbsp;userFunc( f) ;<BR>&nbsp;&nbsp;}<BR>}<BR>假设userFunc 
是一个函数 void f(<BR>FontObject font).这样使用者只需要定义一个函数:<BR>&nbsp;&nbsp;void myfunc( 
FontObject 
font)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>listCtrl.Addstring 
( 
font.name);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR>}<BR>通过使用 EnumFont ( myfunc) 就可以将所有额字体信息添加到一个列表框中。那么我们称 
myfunc是一个回调函数,即让某个系统函数调用的函数。因此可以得出结论:<BR>1 回调函数是由开发者按照一定的原型进行定义的函数<BR>2 
回调函数并不由发者直接调用执行<BR>3 回调函数通常作为参数传递给系统API,由该API来调用。<BR>4 
回调函数可能被系统API调用一次,也可能被循环调用多次。<BR>比如 函数int 
EnumFontFamilies(<BR>&nbsp;&nbsp;HDC<BR>hdc,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
//<BR>handle to device control<BR>&nbsp;&nbsp;LPCTSTR lpszFamily,&nbsp;&nbsp;// 
pointer to family-name string<BR>&nbsp;&nbsp;FONTENUMPROC 
lpEnumFontFamProc,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>// 
pointer to callback function<BR>&nbsp;&nbsp;LPARAM 
lParam&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// pointer 
to<BR>application-supplied data<BR>);<BR>其中的&nbsp;&nbsp; FONTENUMPROC 
lpEnumFontFamProc就是一个回调函数,该函数遵照格式<BR>int CALLBACK EnumFontFamProc( ENUMLOGFONT 
FAR *lpelf,&nbsp;&nbsp;NEWTEXTMETRIC FAR<BR>*lpntm, int 
FontType,&nbsp;&nbsp;LPARAM lParam )进行定义。<BR>如 
同mutant所说,回调函数主要用于一些比较费时的操作,或响应不知道何时将会发生的事件,回调函数提供了一种异步的机制,相对于同步执行,提高了效 
率.前者的例子如WriteFileEx,ReadFileEx等,函数的最后一个参数是一个回调函数的指针,程序中调用WriteFileEx以后,就<BR>直接返回了,可以继续进行其他工作,系统在读写操作完成后通知程序作善后处理.后者的例子就是windows的事件机制回调函数的另一个用途,是用于一些 
枚举函数,如EnumDisplayModes等,每找到一种支持的显示模式,就通知回调函数,由回调函数具体处理,这是因为<BR>EnumDisplayModes本身并不知道用户要如何处理.能,用户提供回调函数,定制系统的功能,这样,不同的用户提供不同的回调函数,可以使系统 
具有不同的功能.这就是所谓的plugin.使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地<BR>址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如 
何定义回调函数,跟具体使用的API函数有关,一般在帮助中有说明回调函数的参数和返回值等。</P><BR>
<P><O:P></O:P></P><BR></DIV>
<DIV style="OVERFLOW-X: hidden; WIDTH: 85%"><IMG 
src="什么是回调函数那_编程论坛.files/sigline.gif"><BR>做个有用的人!</DIV></DIV></DIV>
<DIV class=postbottom2>
<DIV class=postuserinfo style="HEIGHT: 24px">
<DIV style="FLOAT: left"><IMG style="MARGIN: 4px" 
src="什么是回调函数那_编程论坛.files/ip.gif"></DIV>2006-3-26 21:04:00</DIV>
<DIV class=postie 
style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; TEXT-INDENT: 10px; PADDING-TOP: 0px; HEIGHT: 24px">
<DIV style="FLOAT: right; MARGIN-RIGHT: 5px"><A 
href="http://bbs.bc-cn.net/dispbbs.asp?boardID=55&amp;ID=52123#top"><IMG 
style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 3px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" 
alt="" src="什么是回调函数那_编程论坛.files/p_up.gif"></A> </DIV>
<DIV></DIV></DIV></DIV><A name=77380></A><A id=l7 name=7></A>
<DIV class=postlary1>
<DIV class=postuserinfo>
<DIV 
style="FILTER: glow(color='#A6BA98',strength='2'); FLOAT: left; MARGIN: 13px 0px 0px 2px; WIDTH: 123px; LINE-HEIGHT: 23px; HEIGHT: 27px"><FONT 
color=#000066><B>wonglaye</B></FONT></DIV>
<DIV 
style="FLOAT: left; MARGIN: 13px 0px 0px; WIDTH: 23px; TEXT-INDENT: 0px; LINE-HEIGHT: 23px; HEIGHT: 27px"><IMG 
alt=帅哥哟,离线,有人找我吗? src="什么是回调函数那_编程论坛.files/ofMale.gif"> </DIV>
<DIV style="MARGIN: 0px 0px 0px 24px"><IMG height=50 
src="什么是回调函数那_编程论坛.files/54741.gif" width=50><BR><IMG 
style="MARGIN: 1px 0px 2px" 
src="什么是回调函数那_编程论坛.files/level0.gif"><BR>等级:新手上路<BR>文章:27<BR>积分:555<BR>注册:2006年3月26日<BR></DIV></DIV>
<DIV class=postie>
<DIV class=dispbbs_hr>
<DIV style="FLOAT: right"><A title=下一楼 onclick=xl(8) 
href="http://bbs.bc-cn.net/dispbbs.asp?boardID=55&amp;ID=52123#8">第 <FONT 
style="FONT-WEIGHT: bold; COLOR: red">7</FONT> 楼</A> </DIV>&nbsp;<A 
href="mailto:me@wonglaye.net"><IMG alt=点击这里发送电子邮件给wonglaye 
src="什么是回调函数那_编程论坛.files/email.gif" align=middle border=0></A> <A 
href="http://blog.wonglaye.net/" target=_blank><IMG alt=访问wonglaye的主页 
src="什么是回调函数那_编程论坛.files/homepage.gif" align=middle border=0></A> </DIV>
<DIV 
style="TEXT-INDENT: 0px; LINE-HEIGHT: 22px; PADDING-TOP: 5px; HEIGHT: 22px"><B></B></DIV>
<DIV 
style="PADDING-RIGHT: 0px; MARGIN-TOP: 10px; FONT-SIZE: 9pt; OVERFLOW-X: hidden; WIDTH: 97%; WORD-BREAK: break-all; LINE-HEIGHT: normal; HEIGHT: 160px; WORD-WRAP: break-word">
<P>楼上这篇写得不错哦<IMG src="什么是回调函数那_编程论坛.files/em17.gif" align=middle 
border=0><BR>初始化这篇帖子的luckbird所说的WinAPI是调用约定,同样也是为了解决函数栈问题,比如参数入栈出栈的顺序,怎样清理推栈,调用约定分成好几个,有cdecl,stdcall,fastcall等等,MFC默认的是cdecl,而你写的Win32默认的是stdcall,在Win3.0时用PASCAL宏来声明这个约定,而在Win32以后就用WinAPI或者APIENTRY来声明stdcall了,这些调用约束在调试时经常会在调试窗口看到的。<BR>楼上的这篇真的不错,还有那么一点文学味道,喜欢啊</P></DIV>
<DIV style="OVERFLOW-X: hidden; WIDTH: 85%"><IMG 
src="什么是回调函数那_编程论坛.files/sigline.gif"><BR>freedom is not free to 
gain</DIV></DIV></DIV>
<DIV class=postbottom1>
<DIV class=postuserinfo style="HEIGHT: 24px">
<DIV style="FLOAT: left"><IMG style="MARGIN: 4px" 
src="什么是回调函数那_编程论坛.files/ip.gif"></DIV>2006-3-26 21:53:00</DIV>
<DIV class=postie 
style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; TEXT-INDENT: 10px; PADDING-TOP: 0px; HEIGHT: 24px">
<DIV style="FLOAT: right; MARGIN-RIGHT: 5px"><A 
href="http://bbs.bc-cn.net/dispbbs.asp?boardID=55&amp;ID=52123#top"><IMG 
style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 3px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" 
alt="" src="什么是回调函数那_编程论坛.files/p_up.gif"></A> </DIV>
<DIV></DIV></DIV></DIV><A name=77527></A><A id=l8 name=8></A>
<DIV class=postlary2>
<DIV class=postuserinfo>
<DIV 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -