当代码量比较小或者需求固定的时候,可以在一个函数里绑定另一个函数,实现函数互调。但当需要经常改变函数或需要实现动态调用时,绑定的参量就不能实现。这时候需要用到函数指针和函数回调
回调函数:回调函数是一个不显式调用的函数,通过将回调函数的地址传给调用者从而实现调用
函数指针:指向函数的指针,可以把函数指针传入另一个函数作为形参,实现回调,首先声明指针
void f();//这是一个函数原型,无输入,输出void型
void (*)()//左边圆括弧中的星号是函数指针声明的关键,另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数,注意还没有创建函数指针
unsigned psize = sizeof (void (*) ()); // 获得函数指针的大小
void (*p) (); //声明指针,p是指向函数的指针,该函数无输入,返回值的类型为void。左边圆括弧里星号后的就是指针变量名。有了指针变量便可以赋值,
void func()
{
//do something
}
p = func; //p的赋值可以不同,但一定要是函数的地址,并且署名和返回类型相同。
传递回调函数的地址给调用者:现在可以将p传递给另一个函数(调用者) caller(),它将调用p指向的函数,而此函数名是未知的:
void caller(void (*fnp) ())
{
fnp();
}
void func();
int main()
{
p = func;
caller(p); //传递函数地址到调用者
}
如果赋了不同的值给p(不同函数地址),那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。
值的内容是署名匹配的函数名和返回类型。例如:创建指针变量,只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小:
#include <iostream>
int main()
{
void caller(void (*) ()); //函数声明
void func(); //函数声明
void (*p) (); //定义指针变量
p=func; //指针变量赋值
caller(p); //回调
getchar();
}
//回调函数
void caller(void (*fnp) ())
{
printf("调用成功");
fnp();
}
//被调函数
void func()
{
printf("回调成功");
}
这是比较简单的情况,大部分情况被调函数都有形参和返回值,回调函数也有返回值,但分析方法是相同的。