什么是callback函数最简单的解释就是一个函数通过函数指针被调用,如果讲一个函数的地址(也就是指针)作为一个参数传递给另外一个函数,当通过这个指针调用它所指向的函数时,回调就发生了。
那么使用回调函数的动机是什么?设想这样一个问题,我们要对一个list上的每个元素进行任意一种操作,习惯上我们会怎么做呢?肯定是遍历这个list,然后针对每一个元素进行操作,但显然最容易想到往往不是最理想的做法。控制迭代的代码在整个遍历的过程中不断被复制(如for循环),甚至,如果一个异步进程更改了这个list,那么迭代器在遍历过程中可能还会出错。
还有一种做法就是创建一个具有适当同步机制的库函数来进行想要的操作,但这种方法仍然要求库函数里具有遍历list的代码,作为库函数的开发人员,不可能预知每一个应用,而且应用程序的开发人员没必要知道库函数的实现细节。
回调函数弥补了上述的缺点,一个过程用来遍历list,并且该过程里使用基于不同应用的代码操作每个元素。回调函数可以被认为是一种动态绑定。下面我们看一些示例代码。代码是要找到第一个大于6的元素。
最直接的做法:
int i; for (i = 0; i < length; i++) { if (array[i] > 5) { break; } } if (i < length) { printf("Item %d/n", i); } else { printf("Not found/n"); }
回调做法:
/* LIBRARY CODE */ int traverseWith(int array[], size_t length, int (*callback)(int index, int item, void *param), void *param) { int exitCode = 0; for (int i = 0; i < length; i++) { exitCode = callback(i, array[i], param); if (exitCode != 0) { break; } } return exitCode; } /* APPLICATION CODE */ int search (int index, int item, void *param) { if (item > 5) { *(int *)param = index; return 1; } else { return 0; } } /* (in another function) */ int index; int found; found = traverseWith(array, length, &search, &index); if (found) { printf("Item %d/n", index); } else { printf("Not found/n"); }
关于更细节的问题,以后还将继续探讨。