什么是回调函数?
简而言之,回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另
一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。
为什么要使用回调函数?
因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某
种特定原型、某些限制条件(如返回值为int)的被调用函数。
如果想知道回调函数在实际中有什么作用,先假设有这样一种情况,我们要编写一个库,它提供了某些排
序算法的实现,如冒泡排序、快速排序、shell排序、shake排序等等,但为使库更加通用,不想在函数中嵌入
排序逻辑,而让使用者来实现相应的逻辑;或者,想让库可用于多种数据类型(int、float、string),此时,
该怎么办呢?可以使用函数指针,并进行回调。
回调可用于通知机制,例如,有时要在程序中设置一个计时器,每到一定时间,程序会得到相应的通知,
但通知机制的实现者对我们的程序一无所知。而此时,就需有一个特定原型的函数指针,用这个指针来进行回
调,来通知我们的程序事件已经发生。实际上,SetTimer() API使用了一个回调函数来通知计时器,而且,万一
没有提供回调函数,它还会把一个消息发往程序的消息队列。
另一个使用回调机制的API函数是EnumWindow(),它枚举屏幕上所有的顶层窗口,为每个窗口调用一个程
序提供的函数,并传递窗口的处理程序。如果被调用者返回一个值,就继续进行迭代,否则,退出。
EnumWindow()并不关心被调用者在何处,也不关心被调用者用它传递的处理程序做了什么,它只关心返回
值,因为基于返回值,它将继续执行或退出。
不管怎么说,回调函数是继续自C语言的,因而,在C++中,应只在与C代码建立接口,或与已有的回调接
口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或函数符(functor),而不是回调函
数。
回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。回调函数使用
是必要的,在我们想通过一个统一接口实现不同的内容,这时用回掉函数非常合适。比如,我们为几个不同的
设备分别写了不同 的显示函数:void TVshow(); void ComputerShow(); void NoteBookShow()...
等 等。这是我们想用一个统一的显示函数,我们这时就可以用回调函数了。void show(void (*ptr)()); 使
用时根据所传入的参数不同而调用不同的回调函数。
下面举两个例子说明回调该函数的使用
#include<stdio.h>
#include<stdlib.h>
void perfect(int n)
{
int i=1;
int count=0;
for(i=1;i<n;i++)
{
if(0==n%i)
{
count+=i;
}
}
if(count==n)
printf("%d是完数\n",n);
else printf("%d不是完数\n",n);
}
void myCallback(void (*perfect)(int ),int n)
{
perfect(n);
}
int main()
{
int n;
printf("请输入一个正整数\n");
scanf("%d",&n);
myCallback(perfect,n);
return 0;
}
//Test.c
#include <stdlib.h>
#include <stdio.h>
int Test1()
{
int i;
for (i=0; i<30; i++)
{
printf("The %d th charactor is: %c\n", i, (char)('a' + i%26));
}
return 0;
}
int Test2(int num)
{
int i;
for (i=0; i<num; i++)
{
printf("The %d th charactor is: %c\n", i, (char)('a' + i%26));
}
return 0;
}
void Caller1(void (*ptr)())//指向函数的指针作函数参数
{
(*ptr)();
}
void Caller2(int n, int (*ptr)())//指向函数的指针作函数参数,这里第一个参数是为指向函数的指针服务的,
{ //不能写成void Caller2(int (*ptr)(int n)),这样的定义语法错误。
(*ptr)(n);
return;
}
int main()
{
printf("************************\n");
Caller1(Test1); //相当于调用Test2();
printf("&&&&&&************************\n");
Caller2(30, Test2); //相当于调用Test2(30);
return 0;
}
以上通过将回调函数的地址传给调用者从而实现调用,但是需要注意的是带参回调函数的用法。要实现回调,
必须首先定义函数指针。函数指针的定义这里稍微提一下。比如: int (*ptr)(); 这里ptr是一个函数指针,其
中(*ptr)的括号不能省略,因为括号的优先级高于星号,那样就成了一个返回类型为整型的函数声明了