回调函数,之前没有接触过,那就研究研究吧。
最直接的就是,看看一个回调函数的小栗子。
翻阅《c和指针》有一节介绍回调函数,最简单的模型就是:把函数指针作为参数传递给其他函数,然后后者“回调”作为参数的函数。
在网上找一个小代码
#include <stdio.h>
void printWelcome(int len)
{
printf("欢迎欢迎 -- %d\n", len);
}
void printGoodbye(int len)
{
printf("送客送客 -- %d\n", len);
}
void callback(int times, void (* print)(int))
{
int i;
for (i = 0; i < times; ++i)
{
print(i);
}
printf("\n我不知道你是迎客还是送客!\n\n");
}
void main(void)
{
callback(10, printWelcome);
callback(10, printGoodbye);
printWelcome(5);
}
这段代码中callback函数似乎符合,上面描述的要求。
但是这种写法有什么妙处呢?未能体会。
在c和指针指出了一类问题
设想这样问题,需要这样一个接口函数,就是比较两个东西的大小,这两个东西不知道的,可能是整数可能是字符串。
首先对于整数,写出如下
bool cmp(int a,int b)
{
if(a>b)
return true;
else
return false;
}
这时候需要思考的问题:
1、如果是字符串怎么办?
2、如何将这个函数改成通用的函数?
想到strcpy和memcpy这两个函数的源代码
strcpy就是针对字符串的copy,而和一个是对内存,及是任意的。
memcpy实现的是用void*这种方式,
将一个数据进行抽象,一种比较好的方式就是使用指针,从本质上来讲,指针是不区分数据类型的,
比如int*类型的指针实际也是可以用char*来表示的,
将char*再抽象,就是void*本质上就是char*,但是在类型检查时不会有问题。
修改上面函数的参数列表
bool cmp_gen(void* a,void* b)
然而,如何比较也是一个问题,既然是通用接口,那么就把比较函数也作为参数传进来吧
bool cmp_gen(void* a,void* b,bool (*cmp)(void*,void*))
{
if(cmp(a,b))
return true;
else
return false;
}
bool int_cmp(void* a,void* b)
{
if(*(int*)a>*(int*)b)
return true;
else
return false;
}
对于接口函数cmp_gen只需要改变不同的传入参数,就可以了。
接下来就看看在一些已经成熟的工程中有哪些使用了回调函数
在c++中,STL有一个函数,快排
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
就是一个回调函数,
base
Pointer to the first object of the array to be sorted, converted to a void*.
num
Number of elements in the array pointed to by base.
size_t is an unsigned integral type.
size
Size in bytes of each element in the array.
size_t is an unsigned integral type.
compar
Pointer to a function that compares two elements.
This function is called repeatedly by qsort to compare two elements. It shall follow the following prototype:
int compar (const void* p1, const void* p2);
For types that can be compared using regular relational operators, a general compar function may look like:
下面是参数函数的具体实现,
int compareMyType (const void * a, const void * b)
{
if ( *(MyType*)a < *(MyType*)b ) return -1;
if ( *(MyType*)a == *(MyType*)b ) return 0;
if ( *(MyType*)a > *(MyType*)b ) return 1;
}