了解开发语言的朋友应该都会对回调函数有所了解,在很多的程序开发语言中都能看到回调的身影。很多场景下,当某个条件成立以后我们**代码执行某些指定的部分,这个时候可以考虑使用回调函数的方式,这样做思路更加的清晰,也能使代码结构的逻辑更加清晰,结构更加好。 那回调函数的到底是什么呢?它又是怎么实现的呢? 这是本次想要简单分析的一个主题。 但是在说回调函数之前,我觉得很有必要先说明一下“函数指针”这个概念,它是回调函数能够实现的重要基础。 1、函数指针 学习过C语言的伙伴都知道,C语言中的灵魂 — 指针。可以毫不犹豫的说,要检验你对C语言的掌握程度,那指针绝对是最好的考察方式。指针的使用和变幻方式,真正的使用起来能让你眼花缭乱。 下面是常见的指针的定义: int*ptr1; char*ptr2; structstd*ptr3;// 结构体指针 那函数指针到底是什么呢? 函数指针:函数指针是指向函数的指针变量。简单理解是指向函数名的指针变量。 函数指针既然是指向函数的,那么它就可以像函数一样,用于调用函数、传递参数等操作。函数指针的定义方式如下: 函数返回值类型 (* 指针变量名) (函数参数列表);
“函数返回值类型”:表示该指针变量可以指向具有什么返回值类型的函数;
“函数参数列表”:表示该指针变量可以指向具有什么参数列表的函数。
举例如下: int(*func1)(void) int(*func2)(int,char,...) char(*func3)(int,char,...)
...... 从上面的演示可以看到,函数指针的定义就是将一个函数中的 “函数名” 改成“(* 指针变量名)”的方式,从而实现了一个函数指针的定义。 但是这里需要注意的是:“(* 指针变量名)”两端的括号是必须要有的,如果缺少了这对括号,那么这个定义的方式就会变为指针函数。如下: int*func1(void) int*func2(int,char,...) char*func3(int,char,...)
......
这种就不是函数指针了,而是指针函数。两者差别是很大的。 特别需要需要注意的一点是:指向函数的指针变量没有 ++ 和 -- 运算。 对于函数指针,一般为了方便使用,我们会选择另外的一种定义方式: typedef函数返回值类型 (* 指针变量名) (函数参数列表); 比如: typedefint(*Fun1)(int,...); typedefint(*Fun2)(int,int,...); typedefvoid(*Fun3)(void); typedefvoid* (*Fun4)(void*);
......
2.、函数指针的使用方式 清楚了函数指针是什么东西了之后,那函数指针要怎么使用呢?看下面的例子: /* 1.首先定义一个函数 */intFunc(intx);/* 2.然后定义一个函数指针 */int(*p) (intx);/* 3.将Func函数的首地址赋给指针变量p */p = Func;
或
p = &Func;/* 4.然后使用p调用Func函数 */(*p) (intx); 因为函数名 Func 代表函数的首地址,所以经过赋值以后,指针变量 p 保存的就是Func的函数入口地址,即 p 就指向函数 Func() 代码的首地址。 为了加深函数指针的使用方式,看下面的一段代码你就明白了。如下: - #include<stdio.h>
- intMax(int,int);//函数声明
- intmain(void){
- inta, b, c;
- int(*p)(int,int);//定义一个函数指针
- p = Max;//把函数Max赋给指针变量p, 使p指向Max函数
- printf("please enter a and b:");
- scanf("%d %d", &a, &b);
- c = (*p)(a, b);//通过函数指针调用Max函数
- printf("a = %d\nb = %d\nmax = %d\n", a, b, c);
- return0;
- }intMax(intx,inty)//定义Max函数
- {intz;
- if(x > y) z = x;
- else
- z = y;
- return z;
- }
特别注意的是,因为函数名本身就可以表示该函数地址(指针),因此在获取函数指针时,可以直接用函数名,也可以取函数的地址。 p= Max 可以改成 p = &Maxc= (*p)(a, b) 可以改成 c = p(a, b)
3. 函数指针可以作为函数的参数来使用 函数指针变量本身也是一个变量,也可以作为某个函数的参数进行使用的。如下: - #include<stdio.h>
- #include<stdlib.h>// 定义一个函数指针类型的
- FunTypetypedefvoid(*FunType)(int);
- voidmyFun(intx);
- voidhisFun(intx);
- voidherFun(intx);
- voidcallFun(FunType fp,intx);
- intmain(){
- callFun(myFun,1000);//传入函数指针常量,作为回调函数
- callFun(hisFun,5000);
- callFun(herFun,4700);
- return0;
- }
4、回调函数 前面讲了函数指针,现在终于到了回调函数了。到这部分,我们就不说太多的废话,直接阐述回调函数是什么,回调函数要怎么使用,一步到位吧! 回调函数:如果一个函数的指针(函数名或地址)作为参数传递给另外一个函数,当这个指针被用来调用其所指向的函数时,就说这个指针所指向的函数是一个回调函数。 再简明点说:回调函数不是直接调用该函数进行使用的,而是要通过另外的特定事件或者其他函数进行调用的,才能称作回调函数。定义一个函数然后直接调用,都不能称为回调函数。 回调函数的定义方式和使用,直接通过下面的例子说明,相信大家一看就会明白。 例程1:
例程2: - intCallback_1(inta)// 回调函数1{printf("Hello, this is Callback_1: a = %d ", a);return0;
- }intCallback_2(intb)// 回调函数2{printf("Hello, this is Callback_2: b = %d ", b);return0;
- }intCallback_3(intc)// 回调函数3{printf("Hello, this is Callback_3: c = %d ", c);return0;
- }intMyHandle(intx,int(*MyCallback)(int)){
- MyCallback(x);
- }intmain(){
- MyHandle(4, Callback_1);
- MyHandle(5, Callback_2);
- MyHandle(6, Callback_3);return0;
- }
从上面的代码可以看出,MyHandle() 函数的参数有一个指针,在 main() 函数里调用MyHandle() 函数的时候,给它传入了函数 Callback_1()、Callback_2()、Callback_3() 的函数名,这时候的函数名就是对应函数的指针,也就是说,回调函数其实就是函数指针的一种用法。 到处,通过上面的函数指针的说明和回调函数的示例代码,估计看到这里的朋友应该都明白了回调函数的使用了吧!
|