回调函数的概念及其使用

上传人:cl****1 文档编号:504034501 上传时间:2023-09-24 格式:DOCX 页数:11 大小:99.97KB
返回 下载 相关 举报
回调函数的概念及其使用_第1页
第1页 / 共11页
回调函数的概念及其使用_第2页
第2页 / 共11页
回调函数的概念及其使用_第3页
第3页 / 共11页
回调函数的概念及其使用_第4页
第4页 / 共11页
回调函数的概念及其使用_第5页
第5页 / 共11页
点击查看更多>>
资源描述

《回调函数的概念及其使用》由会员分享,可在线阅读,更多相关《回调函数的概念及其使用(11页珍藏版)》请在金锄头文库上搜索。

1、回调函数的概念及其使用回调函数的概念及其使用1什么是回调软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类: 同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方 执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,种事件时,非常紧密,息的通知。0不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系 通常我们使用回调来实现异步消息的注册,通过异步调用来实现消 同步调用是三者当中最简单的,而回调又常常是异步

2、调用的基础,(Win32、JDK)或构架(CORBADCOMWebService),客户和服务的交互除了同步方式以外,者隔!要 具备一定的异步通知机制,让服务方(或接口提供方)在某些情况下能够主动 通知客户,而回调是实现异步的一个最简捷的途径。对于一般的结构化语言,可以通过回调函数来实现回调。回调函数也是一个函 数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。2 / 112010年 5 月 21 日在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种 接口的类成为回调类,回调类的对象成为回调对象。对于象C+ Object Pascal 这些兼容了过程特性的对象

3、语言,不仅提供了回调对象、回调方法等特性,也 能兼容过程语言的回调函数机制。Windows平台的消息机制也可以看作是回调的一种应用,我们通过系统提供的接 口注册消息处理函数(即回调函数),从而实现接收、处理消息的目的。由于 Windows平台的API是用C语言来构建的,我们可以认为它也是回调函数的一个 特例。对于分布式组件代理体系 CORBA异步处理有多种方式,如回调、事件服务、通 知服务等。事件服务和通知服务是 CORBAB来处理异步消息的标准服务,他们 主要负责消息的处理、派发、维护等工作。对一些简单的异步处理过程,我们 可以通过回调机制来实现。下面我们集中比较具有代表性的语言(G Obj

4、ect Pascal )和架构(CORBA来 分析回调的实现方式、具体作用等。2过程语言中的回调(C)2.1 函数指针回调在C语言中是通过函数指针来实现的,通过将回调函数的地址传给被调函数 从而实现回调。因此,要实现回调,必须首先定义函数指针,请看下面的例子:void Func(char *s); / 函数原型void (*pFunc) (char *);/函数指针可以看出,函数的定义和函数指针的定义非常类似。一般的化,为了简化函数指针类型的变量定义,提高程序的可读性,我们需要把函数指针类型自定义一下。typedef void(*pcb)(char *);回调函数可以象普通函数一样被程序调用,

5、但是只有它被当作参数传递给被调 函数时才能称作回调函数。被调函数的例子: void GetCallBack(pcb callback)/*do something*/用户在调用上面的函数时,需要自己实现一个pcb类型的回调函数:void fCallback(char *s)/* do something */然后,就可以直接把fCallback当作一个变量传递给GetCallBack,GetCallBack (fCallback );如果赋了不同的值给该参数,那么调用者将调用不同地址的函数。赋值可以发 生在运行时,这样使你能实现动态绑定。回页首2.2 参数传递规则到目前为止,我们只讨论了函数指

6、针及回调而没有去注意ANSI C/C+的编译器规范。许多编译器有几种调用规范。如在 Visual C+中,可以在函数类型前加 _cdecl ,_stdcall 或者_pascal 来表示其调用规范(默认为 _cdecl )。C+Builder 冠支持_后stcall调用皿范。调用规范影响编译器产生的给箔函数名,参数传递 的顺序(从右到左或从左到右),堆栈清理责任(调用者或者被调用者)以及参 数传递机制(堆栈,CPUS存器等)。将调用规范看成是函数类型的一部分是很重要的;不能用不兼容的调用规范将 地址赋值给函数指针。例如:/被调用函数是以int为参数,以int为返回值_stdcall int c

7、allee(int);/调用函数以函数指针为参数void caller( _cdecl int(*ptr)(int);在p中企图存储被调用函数地址的非法操作_cdecl int(*p)(int) = callee; /出错 指针p和callee()的类型不兼容,因为它们有不同的调用规范。因此不能将被 调用者的地址赋值给指针p,尽管两者有相同的返回值和参数列2.3 应用举例C语言的标准库函数中很多地方就采用了回调函数来让用户定制处理过程。如常用的快速排序函数、二分搜索函数等。快速排序函数原型:void qsort(void *base, size_t nelem, size_t width, i

8、nt (_USERENTRY *fcmp)(const void *, const void *);二分搜索函数原型:void *bsearch(const void *key, const void *base, size_t nelem,size_t width, int (_USERENTRYcmp)(const void *, constvoid *);其中fcmp就是一个回调函数的变量。下面给出一个具体的例子:#include #include int sort_function( const void *a, const void *b);int list5 = 54, 21, 1

9、1,67, 22 ;int main(void)int x;qsort(void *)list, 5, sizeof(list0), sort_function);for (x = 0; x 5; x+)printf(%in, listx);return 0;int sort_function( const void *a, const void *b)return *(int*)a-*(int*)b;3面向对象语言中的回调(Delphi )Dephi与C+一样,为了保持与过程语言 Pascal的兼容性,它在引入面向对象 机制的同时,保留了以前的结构化特性。因此,对回调的实现,也有两种截然 不

10、同的模式,一种是结构化的函数回调模式,一种是面向对象的接口模式。3.1 回调函数回调函数类型定义:typeTCalcFunc=function(a:integer;b:integer):integer;按照回调函数的格式自定义函数的实现,如function Add(a:integer;b:integer):integerbeginresult:=a+b;end;function Sub(a:integer;b:integer):integerbeginresult:=a-b;end;回调的使用function Calc(calc:TcalcFunc;a:integer;b:integer):i

11、nteger下面,我们就可以在我们的程序里按照需要调用这两个函数了c:=calc(add,a,b);/c=a+bc:=calc(sub,a,b);/c=a-b3.2 回调对象什么叫回调对象呢,它具体用在哪些场合?首先,让我们把它与回调函数对比 一下,回调函数是一个定义了函数的原型,函数体则交由第三方来实现的一种 动态应用模式。要实现一个回调函数,我们必须明确知道几点:该函数需要那 些参数,返回什么类型的值。同样,一个回调对象也是一个定义了对象接口, 但是没有具体实现的抽象类(即接口)。要实现一个回调对象,我们必须知道: 它需要实现哪些方法,每个方法中有哪些参数,该方法需要放回什么值。因此,在回

12、调对象这种应用模式中,我们会用到接口。接口可以理解成一个定 义好了但是没有实现的类,它只能通过继承的方式被别的类实现。Delphi中的接口和COMH口类似,所有的接口都继承与Ilnterface (等同于lUnknow),并 且要实现三个基本的方法 Queryinterface, _AddRef,和_Release。定义一个接口type IShape=interface(IInterface) procedure Draw;end实现回调类IID: TGUID; out Obj): HResult;IID: TGUID; out Obj): HResult;type TRect=class(T

13、Object,IShape) protectedfunction Queryinterface(conststdcall;function _AddRef: Integer; stdcall;function _Release: Integer; stdcall;publicprocedure Draw;end;type TRound=class(TObject,IShape) protectedfunction Queryinterface(conststdcall;function _AddRef: Integer; stdcall;function _Release: Integer;

14、stdcall;publicprocedure Draw;end;使用回调对象procedure MyDraw(shape:IShape);varshape:IShape;beginshape.Draw;end;如果传入的对象为TRect,那么画矩形;如果为 TRouncl那么就为圆形。用户 也可以按照自己的意图来实现IShape接口,画出自己的图形:MyDraw(Trect.Create);MyDraw(Tround.Create);3.3 回调方法回调方法(Callback Method)可以看作是回调对象的一部分, Delphi对windows 消息的封装就采用了回调方法这个概念。在有些

15、场合,我们不需要按照给定的 要求实现整个对象,而只要实现其中的一个方法就可以了,这是我们就会用到 回调方法。回调方法的定义如下:TNotifyEvent = procedure(Sender: TObject)of object;TMyEvent=procedure(Sender:Tobject;EventId:Integer) of object;TNotifyEvent是Delphi中最常用的回调方法,窗体、控件的很多事件,如单 击事件、关闭事件等都是采用了 TnotifyEvent。回调方法的变量一般通过事件 属性的方式来定义,如TCustomForm0勺创建事件的定义:property OnCreate: TNotifyEvent read FOnCreate write FOnCreate stored IsForm;我们通过给事件属性变量赋值就可以定制事件处理器。用户定义对象(包含回调方法的对象):type TCallback=Classprocedure Cli

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 商业/管理/HR > 营销创新

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号