C/C++培训
达内IT学院
400-996-5531
维基百科(Wikipedia):在计算机编程中,回调函数是
可执行代码作为参数传入其他的可执行代码,并由其他的可执行代码执行这段可执行代码
的过程。
具体过程(以函数为例1):
A() { // output P } B(fn) { fn(); // B knows only fn, not A // B treats fn as a variable } B(A); // B called at T // B calling fn() (i.e. calling A())
函数 A 作为参数 fn 传入 函数 B
B 不知道 A 的存在,只知道 fn
B 将 fn 当作一个传入函数的局部变量处理
函数 B 通过 fn() 的语法,调用函数 A
B 在 调用时刻 T,调用 fn
B 调用 fn 可能是是为了得到结果 P
对于没有接触过函数式编程 (functional programming) 的初学者,这里有两个难以理解的地方:
函数竟然可以作为参数传递到另一个函数里
函数是程序设计语言中的一等公民 (first-class function)(函数 A)
将函数作为参数的函数,叫做高阶函数 (higher-order function)(函数 B)
通过参数传入的函数 fn,可以直接通过 fn() 的语法调用
生活中的回调函数
场景一
有一个房间里没有灯,只有一个灯座
你给 灯座装上了一盏白炽灯
到了晚上,你打开了灯座上的开关
灯座通了电,点亮了灯座上的那盏灯
于是,那盏白炽灯发出的温暖的光浸满了整个房间
这里对应了例1描述的五个要素:
白炽灯相当于是函数 A
灯座相当于是函数 B
对于灯座来说,灯座上的那盏灯相当于是参数 fn
对于灯座来说,打开灯座上的开关相当于是调用的时刻 T
温暖的光 相当于是 回调结果 P
场景二
一天,你在房间里开了一个聚会,希望把灯光换成彩色的
于是,把灯座上的 白炽灯 换成了 彩灯
当你 打开灯座上的开关时,房间里充满了 彩色的光
场景二和场景一相比,
相同的要素是:灯座、灯座上的那盏灯、打开灯座上的开关
不同的要素是:彩灯、彩色的光
这里说明了回调函数的设计初衷 —— 控制反转,即将控制权下发给回调函数:
灯座不需要知道灯座上的灯是白炽灯还是彩灯
灯座只需要知道灯座上有一盏灯
灯座在你打开灯座上的开关时,会点亮 灯座上有一盏灯
这样就可以换上不同的灯泡,得到不同颜色的灯光。
同步和异步
实际上,不管是什么程序设计语言,回调函数都分为同步和异步两种。这里以 C 语言为例,分析两者的区别。
同步回调
下面的代码展示了如何给一个数组从小到大排序的代码。代码调用了函数 qsort 进行排序,并通过指定 compare 为参数,实现元素大小的比较。
int compare (const void * a, const void * b) { return (*(int*) a - *(int*) b); } ... int values[] = { 20, 10, 50, 30, 60, 40 }; qsort (values, sizeof (values) / sizeof (int), sizeof(int), compare);
代码对应了例1描述的五个要素:
compare 相当于是 函数 A
qsort 相当于是 函数 B
对于 qsort 来说,qsort 的第四个参数相当于是参数 fn
对于 qsort 来说,排序过程中,比较两个元素大小的时刻相当于是调用时刻 T
compare 返回两个元素比较大小的结果 相当于是回调结果 P
由于调用 compare 的时刻 T 均是在调用 qsort 结束之前(qsort 未返回),所以这样的回调被称为同步回调。
异步回调
下面的代码展示了如何在 Linux 下,阻止用户使用 Ctrl C 退出程序,并打印 Press ^C 提示。代码调用了函数 signal 进行回调函数的注册(和同步回调不同,这里仅是注册)。
void block_interrupt (int code) { printf("\rPress ^C\n"); } ... signal (SIGINT, block_interrupt)
代码对应了例1描述的五个要素:
block_interrupt 相当于是函数 A
Linux 终端(Ctrl C 信号的发送者) 相当于是函数 B
调用 signal 函数注册 SIGINT 事件时的参数 相当于是参数 fn
对于 Linux 终端来说,用户按下 Ctrl C 的时刻 相当于是 调用时刻 T
block_interrupt 打印 Press ^C 提示 相当于是回调结果 P
由于调用 block_interrupt 的时刻 T 是用户按下 Ctrl C 的时刻,均是在调用 signal 结束之后(signal 已返回),所以这样的回调被称为异步回调。
同步和异步方式的不同
同步方式通过参数传递 的方法(例如 qsort)传递回调函数;调用者 直接使用回调函数,从而完成回调(调用时刻在函数返回前)
异步方式通过注册 的方式(例如 signal)告知未来的调用者,并 存储回调函数;调用者在未来某个调用时刻 T,取出并调用回调函数,从而完成回调。
免责声明:内容和图片源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。
填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!
Copyright © 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有
Tedu.cn All Rights Reserved