一、回调函数的概念
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数 的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进 行响应。
这个概念是在鹏哥的视频指针进阶部分有讲过的,这段文字很抽象,看了之后还是有点难以get到何为抽象函数是吧?不要担心,马上就来讲解
简单来说就是,把A函数以指针形式传递给B函数,然后在B函数里头用A函数的地址重新去调用A函数的过程就是函数回调。
二、实际演示
鹏哥讲的这个计算器的例子,我觉得用来理解函数回调是再好不过了
首先来看,如果没有使用函数回调的代码是这样子的:
int Add(int x, int y) //定义加法运算
{
return x + y;
}
int Sub(int x, int y) //定义减法运算
{
return x - y;
}
int Mul(int x, int y) //定义乘法运算
{
return x * y;
}
int Div(int x, int y) //定义除法运算
{
return x / y;
}
void menu()
{
printf("**************************\n");
printf("**** 1. add 2. sub ****\n");
printf("**** 3. mul 4. div ****\n");
printf("**** 0. exit ****\n");
printf("**************************\n");
}
int main()
{
int input = 0;
//计算器-计算整型变量的加、减、乘、除
//a&b a^b a|b a>>b a<<b a>b
do {
menu();
int x = 0;
int y = 0;
int ret = 0;
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入2个操作数>:");
scanf("%d %d", &x, &y);
ret = Add(x, y);
printf("ret = %d\n", ret);
break;
case 2:
printf("请输入2个操作数>:");
scanf("%d %d", &x, &y);
ret = Sub(x, y);
printf("ret = %d\n", ret);
break;
case 3:
printf("请输入2个操作数>:");
scanf("%d %d", &x, &y);
ret = Mul(x, y);
printf("ret = %d\n", ret);
break;
case 4:
printf("请输入2个操作数>:");
scanf("%d %d", &x, &y);
ret = Div(x, y);
printf("ret = %d\n", ret);
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
我们可以看到,在switch语句中有大量冗余代码,这在实际开发中是效率极为低下的。
接着我们再来看看使用了函数回调的函数表现如何:
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
void menu()
{
printf("**************************\n");
printf("**** 1. add 2. sub ****\n");
printf("**** 3. mul 4. div ****\n");
printf("**** 0. exit ****\n");
printf("**************************\n");
}
int Calc(int (*pf)(int, int))
{
int x = 0;
int y = 0;
printf("请输入2个操作数>:");
scanf("%d %d", &x, &y);
return pf(x, y);
}
int main()
{
int input = 0;
do {
menu();
int ret = 0;
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
ret = Calc(Add);
printf("ret = %d\n", ret);
break;
case 2:
ret = Calc(Sub);
printf("ret = %d\n", ret);
break;
case 3:
ret = Calc(Mul);//
printf("ret = %d\n", ret);
break;
case 4:
ret = Calc(Div);//
printf("ret = %d\n", ret);
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
可以看到其实函数回调一般都是用于在一个函数中利用传递过来的地址去调用另一个函数,这样可以提高计算机运算的效率。
当然,关于这个计算器的代码还有其他一些优化思路,比如使用函数指针数组进行优化,但这跟本文讨论的主题没有太大关系,所以我会留着以后再讲
三、总结
函数回调就是在把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,这个过程是回调函数。
在某些地方,函数回调使用的好了,可以代码减少不必要的冗余,同时也会增加运算的效率