[转]C++回调函数
回调函数
回调函数是一个时时听到的概念,比如在windows API编程时遇到的WinProc函数,就是我们编写而由操作系统调用的函数。现在,我们需要慢慢又详细的记录一下这个问题。
库与使用者的问题
在开始之前,首先我们想像这样一个情景,一个大型软件公司开发一套软件库提供给用户使用。在这句话中,出现两个对立面,一个是软件公司,一个是用户。显然,软件公司实力很强大,他们强大的地方在于他们很聪明。请看下图:

库开发者是提供方,他们不知道用户想做什么,库开发者对用户的信息是未知的,因为两边的人谁也没见过谁,就像一个人在美国一个人在中国。他们聪明的地方就在于即使不知道用户怎么操作,他们也可以用一种通用的方法来解决用户的问题。换句话说,库开发方不管用户怎么折腾变化,他都能适应。这就是问题的神奇之处,当然,为了达到这种效果,必须有一种规则来约束。
规则
现在来说规则,规则比较好理解,就是两方达成的约束。比如甲和乙两个人,甲对乙说,你只要提供给我一个塑料球,我都能给它涂上颜色。这里的约束是塑料球,(当然,为了简化问题这里的约束还是比较泛泛而不严谨的),这个时候如果乙给他一个水晶球,或者给他一辆汽车都不行,因为已经超越了约束。所以说,库开发者能适应用户的各种变化就在于他也给了用户一定的约束,是在约束之下的适应,这也是不言自明的。
代码之下无秘密
下面一段代码极好的解释了上述问题:
#include <stdio.h> typedef int student_id;
typedef int student_age;
typedef struct _Student{
student_id id;
student_age age;
}Student; //类型重定义:函数指针类型
typedef bool (*pFun)(Student, Student); //-----------------------------------------------
//冒泡排序法:能够按AGE或ID排序,用同一个函数实现
//-----------------------------------------------
void sort(Student stu[],const int num,pFun fun)
{
Student temp; for(int i = 0; i < num; ++i) {
for(int j = 0; j < num - i -1; ++j)
{
if((*fun)(stu[j],stu[j+1]))
{
temp = stu[j];
stu[j] = stu[j+1];
stu[j+1] = temp;
}
}
}
} //-----------------------------------------------
//回调函数:比较年龄
//-----------------------------------------------
bool CompareAge(Student stu1,Student stu2)
{
//更改从大到小还是从小到大的顺序,只需反一下。
if(stu1.age < stu2.age)
return true;
return false;
}
//-----------------------------------------------
//回调函数:比较id
//-----------------------------------------------
bool CompareId(Student stu1,Student stu2)
{
//更改从大到小还是从小到大的顺序,只需反一下。
if(stu1.id < stu2.id)
return true;
return false;
} int main()
{
Student stu[] = {
{1103,24},
{1102,23},
{1104,22},
{1107,25},
{1105,21}}; pFun fun = CompareAge;
int size = sizeof(stu)/sizeof(Student); sort(stu,size,fun); for(int i = 0; i < size; ++i){
printf("%d %d\n",stu[i].id,stu[i].age);
} return 0;
}
通过代码,我们必须分辨出哪个是库提供方,哪个是用户:

sort(...)方法是库开者提供的,只是因为模拟问题所以把它写在一个文件中了,我们可以假想它存放在某个静态库lib里面,这样就和它有了界限。
库开发者提供方法sort(...)供我们调用,形参里面还包括一个函数指针,就是调用用户自己写的函数,也即回调函数。所以它提供了规则,也就是说这个回调函数的形参是什么,返回值又是什么,假如用户对于这个回调函数的形参和返回值啥都不知道,随意写了一个函数放进去,sort方法能接受吗?显然是不行的。
那么用户怎么知道回调函数的形参和返回值等信息呢?库开发方会告知,或者在它的文档里面会有说明,就像在windows API开发窗口程序时提供的WinProc() 函数一样,里面的形参必须一模一样。(这个地方会牵涉到接口)
什么是回?
根据上面的代码,我们知道,库开发方提供了一个方法,然后形参又带有一个函数指针,等着用户去写然后拿来调用,并在其实现中调用了这个函数。站在库开发方的立场,我们可以总结为一句话:库开发方调用了用户的函数(回调函数)。
现在,我们把视角移到回调函数的立场上来看,它被调用了。但同时它也有参数,且传进来的参数是库开发方提供的数据,这里我们又可以总结一句话:回调函数调用了库开发方的数据。
这就是“回”的意思,你调我我也调用你,双方互相调用。

回调函数的重点是什么?
根据上文分析,发现回调函数其实也不是难于理解,我觉得重点在于一定要划分清楚谁是库开发方(也可称为提供方,调用者),谁是用户,把职能划分清楚是最关键的。
---------------------------
[转]C++回调函数的更多相关文章
- 小兔JS教程(三)-- 彻底攻略JS回调函数
这一讲来谈谈回调函数. 其实一句话就能概括这个东西: 回调函数就是把一个函数当做参数,传入另一个函数中.传进去的目的仅仅是为了在某个时刻去执行它. 如果不执行,那么你传一个函数进去干嘛呢? 就比如说对 ...
- 嵌入式&iOS:回调函数(C)与block(OC)传 参/函数 对比
C的回调函数: callBack.h 1).声明一个doSomeThingCount函数,参数为一个(无返回值,1个int参数的)函数. void DSTCount(void(*CallBack)(i ...
- 嵌入式&iOS:回调函数(C)与block(OC)回调对比
学了OC的block,再写C的回调函数有点别扭,对比下区别,回忆记录下. C的回调函数: callBack.h 1).定义一个回调函数的参数数量.类型. typedef void (*CallBack ...
- 理解 JavaScript 回调函数并使用
JavaScript中,函数是一等(first-class)对象:也就是说,函数是 Object 类型并且可以像其他一等对象(String,Array,Number等)一样使用.它们可以"保 ...
- 关于js的回调函数的一点看法
算了一下又有好几个月没写博客了,最近在忙公司android的项目,所以也就很少抽时间来写些东西了.刚闲下来,我就翻了翻之前看的东西.做了android之后更加感觉到手机端开发的重要性,现在做nativ ...
- JS学习:第二周——NO.1回调函数
[回调函数] 定义:把一个函数的定义阶段,作为参数,传给另一个函数: 回调函数调用次数,取决于条件: 回调函数可以传参: 回调函数可以给变this指向,默认是window: 回调函数没有返回值,for ...
- 【java回调】java两个类之间的回调函数传递
背景交代:熟悉用js开发的cordovaAPP:对java一窍不通的我,老师让做一个监测用户拍照事件的功能,无奈没有找到现成的库,无奈自己动手开发java插件~~0基础java GreenHand,祝 ...
- Java|今天起,别再扯订阅和回调函数
编程史上有两个令人匪夷所思的说辞,一个是订阅,一个是回调函数. 我想应该还有很多同学为“事件的订阅”和“回调函数”所困扰,因为事情本来就不应该按这个套路来解释. 多直白,所谓的“回调函数”你完全可以线 ...
- C++ 回调函数的定义与用法
一回调函数 我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理.用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义呢?它和其它函数(比如钩子函 ...
- 通过修改i8042prt端口驱动中类驱动Kbdclass的回调函数地址,达到过滤键盘操作的例子
同样也是寒江独钓的例子,但只给了思路,现贴出实现代码 原理是通过改变端口驱动中本该调用类驱动回调函数的地方下手 //替换分发函数 来实现过滤 #include <wdm.h> #inclu ...
随机推荐
- react-router 路由 入门必看
如果您已经入门reactjs,请绕道~ 这篇博客只适合初学者,初学reactjs的时候,如果你不会webpack,相信很多人都会被官方的例子绕的晕头转向. ES6的例子也会搞死一批入门者.之前一直用的 ...
- ASP.NET Core3.1 中使用MongoDB基本操作
1.安装驱动包 install-package MongoDB.Driver -version 2.11.7 2.配置文件帮助类 ConfigHelper public static class Co ...
- memoのQt自动调整窗口尺寸
折腾了好久,好久.终于搞出一个自认为还算可以的方案: QTimer::singleShot(0, this, [this]{ this->adjustSize(); }); 这个解决方案确实有点 ...
- 版图 shrink
先打开模拟部分的版图,然后在ciw 里面执行 dbCreateXFormPCell(geGetEditCellView() "libName") 然后在"libName& ...
- WebService接口实际场景应用(一)
背景:要求写一套接口测试工具.过程中遇到了WebService接口的问题,遂写下本篇文章. 阶段问题1: 需要利用数据驱动,然后读取excel中的数据并直接调用.但是webService接口与http ...
- Linux 第三节(重定向符,通配符,管道符,转义符,VIM编辑器)
1.输入重定向符 < 2.输出重定向符 将我们的命令原本要输出到屏幕的内容,输出到文件里面 标准信息 > 覆盖> 追加>> 错误信息 2> 覆盖2> ...
- elementUI table 第一列值相等合并
效果如下: 首先:在table上加:span-method="spanMethod" 其次: methods中加两个方法 dataPretreatment() { //表格数据列合 ...
- MyBatis Generator使用方法
第一步:在resources文件夹下创建一个目录mybatis-generator,在目录mybatis-generator下创建文件generatorConfig.xml(此处的目录名可任意取) 第 ...
- PHP5-8各版本特性详解
汇总 PHP5.1: autoload PDO MySQLi 类型约束 PHP5.2: JSON 支持 PHP5.3: 命名空间 匿名函数 闭包 新增魔术方法__callStatic()和__invo ...
- 使用Jquery的.css('border')在火狐不兼容
改成如下就可以兼容火狐.IE.谷歌(border-left-color.border-left-width等)