回调即是调用者A通过调用函数B,并且给B传递一个的函数指针参数C,让B反过来调用这个又调用者指定的函数指针函参C所指向的函数,这就是回调。简单点说,回调就是将函数指针作为函数参数,函数通过这个函数指针来调用另一函数的做法,这也是函数指针的一种用法——作为函数参数。
回调函数也是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。回调函数可以像普通函数一样被程序调用,但是只有它被当作参数传递给被调函数时才能称作回调函数。所以回调函数就是一个函数,只不过它强调的是这个函数指针可以作为函数参数被回调。
回调的意义,可以让调用者制定或指定被调用函数的处理过程。如果用户传递了不同的值给函数参数,那么被调用函数将调用不同地址的函数,这样就能实现被调用函数与被调用函数不同实现方法的动态绑定。
回调函数的用处:如QT中的信号与槽函数的绑定函数connect()、linux中的信号处理函数signal()等;
除了这些已有的实现方法,我们还可以利用回调函数来实现函数的”多态“,实现不同功能的指定,或是同一功能不同类型参数的功能实现方法指定。
以下为例子:
用同一函数实现指定的不同功能:
double add(double a,double b);
double sub(double a,double b);
double mul(double a,double b);
double div(double a,double b);
double db_fun(double a,double b, double (*f)(double,double));
int main(void)
{
double a = 22.2,b = 11.1;
printf("a = %f,b = %f\n",a,b);//在printf 的时候double 用%f 和%lf 都可以,而scanf 时double 只能用%lf
printf("a+b=%lf\n",db_fun(a,b,add));
printf("a-b=%lf\n",db_fun(a,b,sub));
printf("a*b=%lf\n",db_fun(a,b,mul));
printf("a/b=%lf\n",db_fun(a,b,div));
return 0;
}
double db_fun(double a,double b, double (*f)(double,double))
{
return (*f)(a,b);
}
double add(double a,double b)
{
return a+b;
}
double sub(double a,double b)
{
return a-b;
}
double mul(double a,double b)
{
return a*b;
}
double div(double a,double b)
{
return a/b;
}
结果:
a = 22.200000,b = 11.100000
a+b=33.300000
a-b=11.100000
a*b=246.420000
a/b=2.000000
同一功能不同类型参数的功能实现指定:
void add(const void *a,const void *b,void *result,void (*pf)(const void *a,const void *b,void *result));
void cadd(const void *a,const void *b,void *result);
void iadd(const void *a,const void *b,void *result);
void fadd(const void *a,const void *b,void *result);
void dadd(const void *a,const void *b,void *result);
int cmp(const void *a,const void *b, int (*pf)(const void *a,const void *b));
int ccmp(const void *a,const void *b);
int icmp(const void *a,const void *b);
int fcmp(const void *a,const void *b);
int dcmp(const void *a,const void *b);
int scmp(const void *s2,const void *s1);
int main(void)
{
char ca = 'a',cb = 'e',c_result = 0;
int ia = 5,ib = 7,i_result = 0;
float fa = 5.6,fb = 4.8,f_result = 0;
double da = 11.1,db = 9.9,d_result = 0;
//add函数:
add(&ca,&cb,&c_result,cadd);
add(&ia,&ib,&i_result,iadd);
add(&fa,&fb,&f_result,fadd);
add(&da,&db,&d_result,dadd);
printf("%c + %c = %c\n",ca,cb,c_result);
printf("%d + %d= %d\n",ia,ib,i_result);
printf("%f + %f = %f\n",fa,fb,f_result);
printf("%lf + %lf = %lf\n",da,db,d_result);
//cmp函数:
int flag=0;
const char *sa = "abcdif";
const char *sb = "abcdifhmk";
flag = cmp(&ca,&cb,ccmp);
switch(flag)
{
case 1:printf("a > b\n"); break;
case -1:printf("a < b\n");break;
default :printf("a = b\n");break;
}
flag = cmp(&ia,&ib,icmp);
switch(flag)
{
case 1:printf("a > b\n"); break;
case -1:printf("a < b\n");break;
default :printf("a = b\n");break;
}
flag = cmp(&fa,&fb,fcmp);
switch(flag)
{
case 1:printf("a > b\n"); break;
case -1:printf("a < b\n");break;
default :printf("a = b\n");break;
}
flag = cmp(&da,&db,dcmp);
switch(flag)
{
case 1:printf("a > b\n"); break;
case -1:printf("a < b\n");break;
default :printf("a = b\n");break;
}
flag = cmp(sa,sb,scmp);
switch(flag)
{
case 1:printf("a > b\n"); break;
case -1:printf("a < b\n");break;
default :printf("a = b\n");break;
}
return 0;
}
//-------------------------------ADD--------------------------------------------------------------
void add(const void *a,const void *b,void *result,void (*pf)(const void *a,const void *b,void *result))
{
(*pf)(a,b,result);
}
void cadd(const void *a,const void *b,void *result)
{
*((char *)result) = *(char *)a + *(char *)b; //这里只是示范,而实际上字符相加很容易溢出127 或者是得到不可打印字符
}
void iadd(const void *a,const void *b,void *result)
{
*((int *)result) = *(int *)a + *(int *)b;
}
void fadd(const void *a,const void *b,void *result)
{
*((float *)result) = *(float *)a + *(float *)b;
}
void dadd(const void *a,const void *b,void *result)
{
*((double *)result) = *(double *)a + *(double *)b;
}
//-------------------------------CMP---------------------------------------------------------------
int cmp(const void *a,const void *b, int (*pf)(const void *a,const void *b))
{
return (*pf)(a,b);
}
int ccmp(const void *a,const void *b)
{
if(*(char *)a == *(char *)b)
return 0;
else
return *(char *)a > *(char *)b ? 1:-1;
}
int icmp(const void *a,const void *b)
{
if(*(int *)a == *(int *)b)
return 0;
else
return *(int *)a > *(int *)b ? 1:-1;
}
int fcmp(const void *a,const void *b)
{
if(*(float *)a == *(float *)b)
return 0;
else
return *(float *)a > *(float *)b ? 1:-1;
}
int dcmp(const void *a,const void *b)
{
if(*(double *)a == *(double *)b)
return 0;
else
return *(double *)a > *(double *)b ? 1:-1;
}
int scmp(const void *s1,const void *s2)
{
if(s1 == NULL ||s2 == NULL)
{
printf("can't compare , the two string all are NULL !");
return -2;
}
else
return strcmp((char *)s1,(char *)s2);
}
/*
结果:
a + e = //这里只是示范,而实际上字符相加很容易溢出127 或者是得到不可打印字符
5 + 7= 12
5.600000 + 4.800000 = 10.400000
11.100000 + 9.900000 = 21.000000
a < b
a < b
a > b
a > b
a < b