回调函数知识点
提示:文章
文章目录
- 前言
- 一、背景
- 二、回调函数
- 2.1 什么是回调函数
- 2.2 回调函数的重新理解
- 2.3 回调函数事件驱动编程实例
- 三、总结
前言
前期疑问:
本文目标:
一、背景
今天看代码规范,提到了回调函数,又重新理解一下这个概念
二、回调函数
2.1 什么是回调函数
什么是回调函数,回调函数的使用场景
其中这篇文章提到了回调函数的两个运用场景。
一、事件驱动
二、通讯协议的推模式
具体表述形式如下:
回调函数一般适合于以下几种场合:
事件驱动机制
为了简单说明该机制,我们假定有两个类,类A与类B。该模式的工作机制如下:
1.类A提供一个回调函数F,该回调函数执行根据不同的参数,执行不同的动作;
2.类A在初始化类B时,传入回调函数F的函数指针pF;
3.类B根据需要在不同的情况下调用回调函数指针pF,这样就实现了类B来驱动类A,类A来响应类B的动作。通信协议的“推”模式
在我们实际工作中,经常会遇到数据通信的问题。总体来说,两个对象要实现数据通信,有以下两种方式:
“拉”模式(询问)
在该模式下,假定对象A要从对象B中获取实时数据信息,“拉”模式的工作机制如下:
(1)对象A开启一个线程,该线程执行一个循环,每隔一定时间间隔,向对象B发出数据请求;
(2)对象B一旦有新的信息,就利用对象B的数据请求,将信息发送给对象A。
注意:该模式的主要问题是需要维护一个循环线程。时间间隔太长会导致,通信的实时性下降;时间间隔太短,会导致CPU浪费太多。
“推”模式(上报)
在该模式下,假定对象A要从对象B中获取实时数据信息,“推”模式的工作机制如下:
(1)对象A在调用对象B时,向其传递一个回调函数;
(2)对象B一旦有新的信息,就调用对象A传递过来的函数指针,将最新的信息发送给对象A。
注意:该模式完美解决了“拉“模式产生的问题,不但保证了数据传输的实时性,而且降低了无用的CPU消耗。一般的通信协议,建议采用”推“模式。
2.2 回调函数的重新理解
表述的文字有点不好理解。我就想查一下有没有具体的代码实现形式。在查资料的过程中,我就自己尝试思考,假如我要解释回调函数给别人听,我应该怎样表述?
我想到了一个点:什么叫回调函数?
比如去找工作,人力资源说可能要人,但是要等老板回来问一下才知道要不要人。于是我就回去了。正常情况下,我需要经常打电话去问下:老板回来了吗?需要人吗?这样我就等于是不停地去询问,对于CPU来说,CPU一直发请求,就是占用了资源。这时候换成一个优化方案,我给人力资源一个电话号码,问过老板就打电话告诉我。这个时候就是利用了回调的机制,这个号码就是回调函数。
更进一步,如果在这个回调函数中增加入职的流程。那么整体的事情就变成了这样。本来我是要不停询问是否可以入职,得到回复后就进行入职流程。因为使用了回调机制,事情就变成人力资源打电话让我入职并启动入职流程。
2.3 回调函数事件驱动编程实例
下面是关于查找时间驱动的代码实例,找到了下面的一篇文章
【C语言指针进阶讲解】第四章:函数指针(回调函数,事件驱动编程)
其中有事件驱动代码实例
#include <stdio.h>
typedef void (*EventHandler)(); // [1]
void handleKeyPress() {
printf("Key pressed.\n");
}
void handleMouseClick() {
printf("Mouse clicked.\n");
}
void processEvent(int event, EventHandler handler) { // [2]
if (handler != NULL) {
handler(); // [3]
} else {
printf("No handler for this event.\n");
}
}
int main() {
int event;
printf("Select event:\n1. KeyPress\n2. MouseClick\n");
scanf("%d", &event);
switch (event) {
case 1:
processEvent(event, handleKeyPress);
break;
case 2:
processEvent(event, handleMouseClick);
break;
default:
printf("Unknown event.\n");
}
return 0;
}
上述代码应该是界面编程,根据界面获取的动作调用相关动作。
上述代码还涉及到了typedef的用法。
三、总结
未完待续