C/C++回调函数初探

简介

对于很多初学者来说,往往觉得回调函数很神秘,很想知道回调函数的工作原理。本文将要解释什么是回调函数、它们有什么好处、为什么要使用它们等等问题,在开始之前,假设你已经熟知了函数指针。

什么是回调函数?

简而言之,回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。

为什么要使用回调函数?

因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。

如果想知道回调函数在实际中有什么作用,先假设有这样一种情况,我们要编写一个库,它提供了某些排序算法的实现,如冒泡排序、快速排序、shell排序、shake排序等等,但为使库更加通用,不想在函数中嵌入排序逻辑,而让使用者来实现相应的逻辑;或者,想让库可用于多种数据类型(int、float、string),此时,该怎么办呢?可以使用函数指针,并进行回调。

回调可用于通知机制,例如,有时要在程序中设置一个计时器,每到一定时间,程序会得到相应的通知,但通知机制的实现者对我们的程序一无所知。而此时,就需有一个特定原型的函数指针,用这个指针来进行回调,来通知我们的程序事件已经发生。实际上,SetTimer() API使用了一个回调函数来通知计时器,而且,万一没有提供回调函数,它还会把一个消息发往程序的消息队列。

另一个使用回调机制的API函数是EnumWindow(),它枚举屏幕上所有的顶层窗口,为每个窗口调用一个程序提供的函数,并传递窗口的处理程序。如果被调用者返回一个值,就继续进行迭代,否则,退出。EnumWindow()并不关心被调用者在何处,也不关心被调用者用它传递的处理程序做了什么,它只关心返回值,因为基于返回值,它将继续执行或退出。

不管怎么说,回调函数是继续自C语言的,因而,在C++中,应只在与C代码建立接口,或与已有的回调接口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或函数符(functor),而不是回调函数。

一个简单的回调函数实现

下面创建了一个sort.dll的动态链接库,它导出了一个名为CompareFunction的类型--typedef int (__stdcall *CompareFunction)(const byte*, const byte*),它就是回调函数的类型。另外,它也导出了两个方法:Bubblesort()和Quicksort(),这两个方法原型相同,但实现了不同的排序算法。

void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc);
void DLLDIR __stdcall Quicksort(byte* array,int size,int elem_size,CompareFunction cmpFunc);

这两个函数接受以下参数:

·byte * array:指向元素数组的指针(任意类型)。

·int size:数组中元素的个数。

·int elem_size:数组中一个元素的大小,以字节为单位。

·CompareFunction cmpFunc:带有上述原型的指向回调函数的指针。

这两个函数的会对数组进行某种排序,但每次都需决定两个元素哪个排在前面,而函数中有一个回调函数,其地址是作为一个参数传递进来的。对编写者来说,不必介意函数在何处实现,或它怎样被实现的,所需在意的只是两个用于比较的元素的地址,并返回以下的某个值(库的编写者和使用者都必须遵守这个约定):

·-1:如果第一个元素较小,那它在已排序好的数组中,应该排在第二个元素前面。

·0:如果两个元素相等,那么它们的相对位置并不重要,在已排序好的数组中,谁在前面都无所谓。

·1:如果第一个元素较大,那在已排序好的数组中,它应该排第二个元素后面。

时间: 2024-11-03 12:01:15

C/C++回调函数初探的相关文章

解决ajax回调函数返回的字符串乱码问题

  ajax回调函数,返回的字符串乱码问题很是让人痛恨,下面有个不错的解决方法,大家可以参考下 ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");//解决乱码问题,没有这句,回调函数的内容可能乱码 ServletActionContext.getResponse().getWriter().write("字符串内容");//在写入之前执行上面一句,可以解决乱码  

回调函数

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

js中回调函数问题,程序进不了回调函数

问题描述 js中回调函数问题,程序进不了回调函数 我这段代码的回调函数哪出错,请各位大神指教 function req(){ createRequest(); var zipcode=document.getElementById(""zipcode"").value; var url=""b.jsp?zipcode="" + escape(zipcode); request.open(""POST&quo

C/C++回调函数

回调函数就像您随身带的BP机:告诉别人号码,在它有事情时Call您        回调用于层间协作,上层将本层函数安装在下层,这个函数就是回调,而下层在一定条件下触发回调,例如作为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的处理工作外,还将进行回调,将这个数据交给上层应用层来做进一步处理,这在分层的数据通信中很普遍.        其实回调和API非常接近,他们的共性都是跨层调用的函数.但区别是API是低层提供给高层的调用,一般这个函数对高层都是已知的:而回调正好相反,他是高层提供给

python回调函数用法实例分析

  这篇文章主要介绍了python回调函数用法,较为详细的分析了常用的调用方式,并实例介绍了Python回调函数的使用技巧,需要的朋友可以参考下 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步调用.同步调用是一种阻塞式调用,调用方要等待对方执行完毕 才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它 的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,

上传-jQuery ajax form提交在IE8下不执行回调函数

问题描述 jQuery ajax form提交在IE8下不执行回调函数 // 上传文件function myUploadExcel(obj) {var options = { url : ""${ctx}/ins/pro/upLoadTempFile.do?filename=""+obj.value dataType : ""text"" beforeSubmit : function(formDatajqFormoption

理解javascript 回调函数

在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A.我们就说函数A叫做回调函数.如果没有名称(函数表达式),就叫做匿名回调函数.因此callback 不一定用于异步,一般同步(阻塞)的场景下也经常用到回调,比如要求执行某些操作后执行回调函数. 例子 一个同步(阻塞)中使用回调的例子,目的是在func1代码执行完成后执行func2. var func1=function(callback){     //do something

Jquery 实现层的拖动,支持回调函数

最近在写一个CMS内容管理系统,前台基本是用ajax异步请求服务器,通过ashx处理,返回json格式处理.由于需要更加人性化的界面,所以采用到了拖动层的操作. 以下是拖动层的主要核心方法,本来想写成插件的,考虑的没那么多时间,就以方法的方式了. /*  * Jquery 鼠标左键拖动面板  * coder:新生帝  * obj:jQuery选择器名称  * callback:回调函数(拖动停止要执行的函数),可通过$(this)获取 obj 对象  */  function movePanel

Promise模式将JS回调函数和异步函数彻底分离

文章简介:情况再复杂点,如果一个操作要等到多个异步 ajax 请求的完成才能进行,就会出现回调函数嵌套的情况,如果需要嵌套好几层,那你就只能自求多福了. 网页的交互越来越复杂,JavaScript 的异步操作也随之越来越多.如常见的 ajax 请求,需要在请求完成时响应操作,请求通常是异步的,请求的过程中用户还能进行其他的操作,不会对页面进行阻塞,这种异步的交互效果对用户来说是挺有友好的.但是对于开发者来说,要大量处理这种操作,就很不友好了.异步请求完成的操作必须预先定义在回调函数中,等到请求完