回调函数与函数指针
用途
1、许多窗口就是通过回调函数来实现的,不同的按钮执行不同的函数
2、菜单处理
3、消息或事件机制也可以看作是一种回调机制
函数回调的实现方式
一般由函数指针实现,将函数的地址作为参数传递给调用他的函数,当函数执行到主调函数时,通过函数指针(即地址)找到被调用的函数,实现被调函数的功能,用函数回调的方式配合void *可以增加代码的通用性,只要函数指针所指向函数类型确定,就可以将同类型的函数的地址传递给主调函数,传递不同函数地址,用同一个主调函数实现不同的功能,可以通过以下代码来说明
#include <stdio.h>
#include <math.h>
//枚举类型声明
typedef enum ERR1
{
DAYU,
XIAOYU
}ERR;
//函数声明
ERR F_Comp(const void *a, const void *b);
ERR I_Comp(const void *a, const void *b);
int GetResult(const void *a, const void *b, ERR (*Comp)(const void *n, const void *b));
int main()
{
int a =9;
int b = 2;
float c = 89.0;
float d = 38.0;
GetResult((void *)(&c), (void *)(&b), I_Comp); //回调函数为整型比较函数
printf("\n-------------------------------------------\n");
GetResult((void *)&d, (void *)&c, F_Comp); //回调函数为浮点数比较函数
printf("\n");
return 0;
}
//函数的第三个参数为函数指针,传递回调函数的地址
int GetResult(const void *a, const void *b, ERR (*Comp)(const void *n, const void *b))
{
//ERR err;
Comp(a, b); //通过函数指针调用函数
return 0;
}
//整型数的比较
ERR I_Comp(const void *a, const void *b)
{
if(*(int *)a > *(int *)b) //强制类型转换
{
printf("%d > %d\n", *(int *)a, *(int *)b);
return DAYU;
}
else
{
printf("%d <= %d\n", *(int *)a, *(int *)b);
return XIAOYU;
}
}
//浮点数的比较
ERR F_Comp(const void *a, const void *b)
{
if(fabsf(*(float *)a - *(float *)b) > 0.00001)
{
printf("%f > %f\n", *(float *)a, *(float*)b);
return DAYU;
}
else
{
printf("%f <= %f\n", *(float *)a, *(float *)b);
return XIAOYU;
}
}
主函数中给GetResult函数传递的函数地址分别为I_Comp、F_Comp,所以通过统一的函数GetResult获得了整型数和浮点数的比较结果
注意到GetResult函数参数都是void *型的,代表他可以接受任意类型的参数,而函数指针所指向函数的类型的参数接受的也是void *类型的参数,至于具体处理什么样的数据,则是由回调函数自己来定义的,I_Comp、F_Comp函数在函数体内部分别将void *型的数据强制转换成了整型指针和浮点型指针,明确了所要操作的数据类型,所以GetResult函数根本不关心回调函数是如何实现的,它只要知道回调函数的入口地址就可以了,不同的回调函数入口地址不同,自然实现的功能也就不同,但这样做统一了函数接口的