[转]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 ...
随机推荐
- 时钟频率(HZ)与数据传输速率(bit/s)的关系-转载
(24条消息) 时钟频率(HZ)与数据传输速率(bit/s)的关系_子曰小玖的博客-CSDN博客_速率和频率的关系 时钟频率(HZ)与数据传输速率(bit/s)两者是相同的概念.举例:IIC传输位速率 ...
- 页面-vue-功能
一. 数组添加/修改数据 使用map this.list.map(i => { i.show = false return i }) 使用foreach this.list.forEach(i ...
- Date 日期字符串自定义格式化
Date.prototype.Format = function (fmt) { var o = { "M+": this.getMonth() + 1, //月份 "d ...
- idea引入ojdbc包报错
网上下载或者让同事传两个jar过来,ojdbc6-11.2.0.7.0.jar 以及jconn3.0.jar 放入同一个文件夹中: 在此文件夹中cmd如下:回车,进入cmd控制台. 输入如下两个命令: ...
- JS篇(009)-javascript 对象的几种创建方式
答案: 第一种:Object 构造函数创建 var Person = new Object(); Person.name = "Nike"; Person.age = 29; 这行 ...
- maven install 报错 The POM for com.oracle:ojdbc6:jar:11.2.0.7.0 is missing, no dependency information available
The POM for com.oracle:ojdbc6:jar:11.1.0.7.0 is missing, no dependency information available The POM ...
- Flutter之EdgeInsets
EdgeInsets我们看看EdgeInsets提供的便捷方法: fromLTRB(double left, double top, double right, doublebottom):分别指定四 ...
- Cxf框架中@WebService注解的使用
最近工作中总是不可避免的使用WebService来对接功能,经过自己一番摸索,总结出了一些使用方法,做一下记录: 记录了两个SpringBoot版本使用WebService的一些问题和用法,Sprin ...
- rabbitMq安装 - docker
安装rabbitmq 参考网站:https://www.rabbitmq.com/download.html 方式一: 获取rabbit镜像: docker pull rabbitmq:managem ...
- Http 包头里面有个content-length,可以获取下载的资源包大小
NSDictionary *headerFieldsDic = request.responseHeaders; 包大小为:[headerFieldsDic[@"Content-Length ...