回调函数
回调函数
回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。回调函数使用是必要的,在我们想通过一个统一接口实现不同的内容,这时用回掉函数非常合适。比如,我们为几个不同的设备分别写了不同的显示函数: void TVshow(); void ComputerShow(); void NoteBookShow()... 等等。这是我们想用一个统一的显示函数,我们这时就可以用回掉函数了。 void show(void (*ptr)()); 使用时根据所传入的参数不同而调用不同的回调函数。
不同的编程语言可能有不同的语法,下面举一个 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);
}
int main()
{
printf("************************\n");
Caller1(Test1); //相当于调用 Test1();
printf("&&&&&&************************\n");
Caller2(30, Test2); //相当于调用 Test2(30);
return 0;
}
以上通过将回调函数的地址传给调用者从而实现调用,但是需要注意的是带参回调函数的用法。要实现回调,必须首先定义函数指针。函数指针的定义这里稍微提一下。比如:
int (*ptr)(); 这里 ptr 是一个函数指针,其中 (*ptr) 的括号不能省略,因为括号的优先级高于星号,那样就成了一个返回类型为整型的函数声明了。
// 例子2. #include <stdlib.h> #include <stdio.h>
#define METHOD 1
int Test1(void) { int i; for(i=0; i<5; 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; }
#ifdef METHOD typedef int (* callback1)(void);
//typedef int (* callback2)(int); 这个声明也是ok 的.. typedef int (* callback2)(int num);
void Caller1( callback1 ptr )//指向函数的指针作函数参数 { printf("method 1------caller1............\n"); ptr(); }
void Caller2(int n, callback2 ptr)//指向函数的指针作函数参数,这里第一个参数是为指向函数的指针服务的, { printf("method 1------caller1............\n"); ptr(n); }
#else
void Caller1( int (*ptr)() )//指向函数的指针作函数参数 { printf("method 2------caller1............\n"); (*ptr)(); }
//以下三种方式定义都ok !!!! //void Caller2(int n, int (*ptr)() ) //void Caller2(int n, int (*ptr)(int) ) void Caller2(int n, int (*ptr)(int num) )//指向函数的指针作函数参数,这里第一个参数是为指向函数的指针服务的, { printf("method 2------caller2............\n"); //不能写成void Caller2(int (*ptr)(int n)),这样的定义语法错误。 (*ptr)(n); }
#endif
int main(void) { printf("\n\n"); printf("************************\n"); Caller1(Test1); //相当于调用Test1(); printf("\n\n\n"); printf("&&&&&&************************\n"); Caller2(8, Test2); //相当于调用Test2(30); printf("\n\n"); return 0; }
// 实例3 #include<stdio.h>
// 方法指针的格式为:int (*ptr)(char *p) 即:返回值(指针名)(参数列表) typedef int (*CallBackFun)(char *p); // 为回调函数命名,类型命名为 CallBackFun,参数为char *p
int Afun(char *p) { // 方法 Afun,格式符合 CallBackFun 的格式,因此可以看作是一个 CallBackFun printf("Afun ,callback print the string is :%s!\n", p); return 0; }
int Cfun(char *p) { // 方法 Bfun,格式符合 CallBackFun 的格式,因此可以看作是一个 CallBackFun printf("Cfun ,callback print the string is :%s, Nice to meet you!\n", p); return 0; }
int call(CallBackFun pCallBack, char *p) { // 执行回调函数,方式一:通过命名方式 printf("call method 1, the string is :%s!\n", p); pCallBack(p); return 0; }
// int call2(char *p, int (*ptr)(char *p)) int call2(char *p, int (*ptr)()) { // 执行回调函数,方式二:直接通过方法指针 printf("=======call method 2, the string is :=======\n", p); (*ptr)(p); }
int main() {
char *p = "hello";
call(Afun, p); call(Cfun, p); printf("\n"); printf("\n");
call2(p, Afun); call2(p, Cfun); printf("\n"); printf("\n"); // int i = getchar(); // printf("Input: %c \n", i);
return 0; }