1回调函数定义
回调函数就是一个通过函数指针调用的函数。即是把函数指针作为参数传入另外一个函数,当这个指针被用来调用其所指向的函数时,该函数就是回调函数。
通俗的解释:
一般来说,编程分为两类:系统编程和应用编程。所谓系统编程,通俗的就是编写库函数;而应用编程就是利用写好的各种库去实现自己想要实现的具体功能,这也就是常说的应用开发,系统程序员(编写库函数的)会给自己的库留一些接口,即是应用程序编程接口API,一般情况下,我们的应用程序会调用已经写好 的库函数,实现预先已经写好的库函数功能,但是有些库函数却要求应用程序需要传入一个函数(函数作为入参)然后才能实现相应的功能,这个被传入然后又被调用的函数就是回调函数。
打一个比方,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方式,可以是打客房电话,也可以是去敲客房门,睡得死怕耽误事的,还可以要求往自己头上浇水。在这里,“叫醒”这个行为是旅客提供的,相当是库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数,而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作成为登记回调函数
2回调函数的实质
就是将函数A作为入参传入另外一个函数B,在函数B中执行A。函数就是地址,所以入参的形参为函数指针。
3回调函数的优势
同样都是调用函数,为什么需要回调函数这样的方式而不是直接调用函数呢?
回调函数在库函数和应用函数之间提供了非常大的灵活性,另外回调函数不仅仅在应用和库函数之间。任何时候,我们只要想要实现类似前者的灵活性,都可以调用回调。
void callBack_water(void)
{
printf("泼水叫醒\n");
}
void callBack_phone(void)
{
printf("电话叫醒\n");
}
void callBack_knock(void)
{
printf("敲门叫醒\n");
}
void wakeup_service(void(*callback)())
{
printf("<酒店叫醒服务>\n");
callback();
}
int main()
{
wakeup_service(callBack_water);
wakeup_service(callBack_phone);
wakeup_service(callBack_knock);
return 0;
}
运行效果:
4回调函数的适用条件
1,模块之间相互独立,存在着相互调用关系
2,两个模块处于不同的层次,为了确保单向依赖(单向调用),通常在下层设置函数指针,然后在上层设置回调函数。
举例说明:
Test.c
/*Test.c*/
int cnt = 0;
/*函数指针*/
void(*fTest)(void) = NULL;
void run(void)
{
while (1)
{
if (fTest!= NULL)
{
f();
}
cnt ++;
}
}
void CallBack_Install(void (*callback)(void))
{
fTest = callback;
}
main.c
/*main.c */
/*main 函数为上层应用 run 函数为底层 回调函数就将上层和低层很好的解耦合*/
void myCallBackFunc()
{
printf("这是回调函数\n");
}
int main()
{
CallBack_Install(myCallBackFunc);
run();
}
运行效果
低层往上层传递数据:
Test.c
/*Test.c*/
int cnt = 0;
/*函数指针*/
void(*fTest)(int) = NULL;
void run(void)
{
while (1)
{
if (fTest!= NULL)
{
f(cnt);
}
cnt ++;
}
}
void CallBack_Install(void (*callback)(int))
{
fTest = callback;
}
main.c
/*main.c */
/*main 函数为上层应用 run 函数为底层 回调函数就将上层和低层很好的解耦合*/
void myCallBackFunc(int data)
{
printf("这是回调函数 %d\n",data);
}
int main()
{
CallBack_Install(myCallBackFunc);
run();
}
运行效果: