最近学习走读代码的时候经常看到回调函数 (call back function),以前的时候也经常听人说起回调,但一直没详细了解过它是什么。于是乎,我今天花了一天时间去理解它。然而还是不太懂什么是回调,直到看到一个以前刷ACM题的时候一个应用场景。
首先,通过查阅了大量的博客,对回调进行一个简单的释义吧。在函数调用时,若传进的参数为函数指针,那么该函数指针所指的函数就是回调函数。
void fun1(int a)
{
cout<<a - 1<<endl;
return ;
}
void fun2(int x, void (*p)(int a))
{
p(x);
return ;
}
int main(int argc, char *argv[])
{
fun2(5, fun1);
return 0;
}
上述代码段中fun1函数就是一个回调函数。这是回调的简单用法,就是自己实现,然后把函数指针传进另一个函数中。
讲到这,你应该知道什么是回调了,但是不知道回调有什么作用应用场景和实际中的应用。
继续举个栗子,c中有个函数叫做qsort,它有一个参数是让你自定义一个函数,然后传函数指针进去。
恩,我们来看下具体的。
int cmp(const void *a,const void *b)
{
return (int *)a - (int *)b > 0;
}
int main(int argc, char *argv[])
{
int a[5] = {1, 5, 2, 4, 3};
qsort(a, 5, sizeof(int), cmp);
return 0;
}
执行完,会发现a中的元素按序排好了,回调的一个应用场景就体现出来了,qsort本身是一个标准库的排序算法,你不需要知道它内部的实现,只需要传进一系列基本参数和一个cmp自定义的比较函数(回调),就可以让它按照你cmp中的比较方式执行排序。试想qsort和调用qsort的函数是两个不同的模块,qsort是别人提供给你的接口,你不需要知道它的实现,只管传参就行了,而其中的一个参数cmp是你自定义的一个函数。这就是回调,与普通调用不同,对于调用的接口反而要传你的实现传给接口。
提炼出一种场景,调用接口的同时,接口内的执行需要传你的实现。那该种用法有什么好处呢,这就是一个程序拓展性的问题了,你在cmp中的实现完全可以写在qsort内部,但是当你用到一种新的比较方式,而这种方式是qsort内部所没有的,此时你可以再qsort内部修改,但显然这是不好的(当然你可以在里面改)。程序讲究复用性,如果此时使用回调函数,场景就变得简单许多,只需要把自己新定义的比较方式通过回调传入进去即可,对于不同的场景,自定义不同的实现,而不需要修改底层。
另外,回调的作用并只有上述复用性的提升。未完。