回调函数
一、回调函数是什么?what?
写在前面:
大神的理解:A "callback" is any function that is called by another function which takes the first function as a parameter。
回调函数被调用时传递了这个函数的指针。
回调的过程有三个函数。F1
函数调用了F2
函数,F2
函数是调用了F3
函数的函数。
函数F1
调用函数F2
的时候,函数F1
向函数F2
传入函数F3
的指针。函数F2
执行时,F3
调用了函数F3
,这个过程就是回调。所以函数F3
就称为回调函数。
对于回调函数来说,它的指针传入由F1
来完成,在F2
执行的时候,被调用。
二、为什么用回调函数?why?
先说一下回调函数的好处:
如上图所示。根据理论,main program
为函数F1
,Library function
为函数F2
,Callback function
为函数F3
。
这种方式可以将调用分为两层,实际的使用的回调函数的定义是在一层的。F2
可以被单独分层,定义好以后可以被封装成lib
库,提供接口以后,定义F3
,在F1
中给F2
传入参数,同时传入F3
的指针。调用F2
即可。完成了解耦,方便不同层的调用。
基本上回调函数的作用就是用来两个线程之间的信息的传递。这就是一种信息传递的方式。传入的内容变成了函数的指针。
图中的例子可以用代码诠释如下:
#include<sting>
#include<iostream>
#include<softwareLib.h> // 包含Library Function所在读得Software library库的头文件
int Callback() // Callback Function//F3
{
// TODO
return 0;
}
int main() // Main program//F1
{
// TODO
Library(Callback);//F2
// TODO
return 0;
}
三、回调函数怎么用?how?
1、不加参数的回调函数
#include<string>
#include<iostream>
using namespace std;
int Callback_1() // Callback Function 1//F3
{
cout<<"Hello, this is Callback_1."<<endl;
return 0;
}
int Callback_2() // Callback Function 2//F3
{
cout<<"Hello, this is Callback_2."<<endl;
return 0;
}
int Callback_3() // Callback Function 3//F3
{
cout<<"Hello, this is Callback_3."<<endl;
return 0;
}
int Handle(int (*Callback)())//F2
{
cout<<"Entering Handle Function."<<endl;
Callback();
cout<<"Leaving Handle Function."<<endl;
}
int main()//F1
{
cout<<"Entering Main Function."<<endl;
Handle(Callback_1);
Handle(Callback_2);
Handle(Callback_3);
cout<<"Leaving Main Function."<<endl;
return 0;
}
运行结果如下:
Entering Main Function.
Entering Handle Function.
Hello, this is Callback_1.
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_2.
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_3.
Leaving Handle Function.
Leaving Main Function.
2、带一个参数的回调函数
#include<string>
#include<iostream>
using namespace std;
int Callback_1(int x) // Callback Function 1//F3
{
cout<<"Hello, this is Callback_1: x = "<< x <<endl;
return 0;
}
int Callback_2(int x) // Callback Function 2//F3
{
cout<<"Hello, this is Callback_2: x = "<< x <<endl;
return 0;
}
int Callback_3(int x) // Callback Function 3//F3
{
cout<<"Hello, this is Callback_3: x = "<< x <<endl;
return 0;
}
int Handle(int y, int (*Callback)(int))//F2
{
cout<<"Entering Handle Function."<<endl;
Callback(y);
cout<<"Leaving Handle Function."<<endl;
}
int main()//F1
{
int a = 2;
int b = 4;
int c = 6;
cout<<"Entering Main Function."<<endl;
Handle(a, Callback_1);
Handle(b, Callback_2);
Handle(c, Callback_3);
cout<<"Leaving Main Function."<<endl;
return 0;
}
运行结果如下:
Entering Main Function.
Entering Handle Function.
Hello, this is Callback_1: x = 2
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_2: x = 4
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_3: x = 6
Leaving Handle Function.
Leaving Main Function.
可以看到在带参数的回调函数中,需要在调用回调函数的函数即F2
中传入回调函数的参数和回调函数的指针。
同时,为便于简便,F2
函数中的回调函数的指针可以用typedef
的方式进行声明。声明的格式如下:
typedef int (*Callback)(int);
声明以后,可以将Handle
函数改成如下所示:
int Handle(int y, Callback cb)
{
cout<<"Entering Handle Function."<<endl;
cb(y);
cout<<"Leaving Handle Function."<<endl;
}
3、带notify
函数的回调函数
在实际的使用过程中,希望能在触发后在使用回调函数,因为回调函数的参数可能不是立即传给它的,存在数据到来的延迟。那么需要有一个函数的作用是接到参数,接到参数以后,通知给调用回调函数的函数,即函数F4
。
F4
与F3
和F1
都在同一层。在使用的时候,在F1
中调用F2
即可。在F1
调用的这一层,先声明一个回调函数的指针,对回调函数F3
进行实际操作,将F3
传入F2
,再新建一个传参函数F4
,将所有参数塞进提前声明好的回调函数指针里。
为便于理解,可以将带有和不带有notify
函数的使用过程进行对比。
不带notify
函数的回调函数使用:
#include <string>
#include <iostream>
using namespace std;
typedef void (*callback)(int);
int register_observer(callback cbk,int i)//注册回调函数并将参数i传递给回调函数//F2
{
cbk(i);
}
void callback_func(int i)//F3
{
printf("callback_func received i=%d\n",i);
}
int main()//F1
{
int i=0;
register_observer(callback_func,6);
return 0;
}
运行结果如下:
listen received i=6
带notify
函数的回调函数的使用:
#include <string>
#include <iostream>
using namespace std;
typedef void (*callback)(int);//F2层
callback cb;//声明一个callback指针,非常关键的一步//在被封装层实现//F2层
void callback_func(int i)//F3
{
printf("callback_func received i=%d\n",i);
}
int register_observer(callback cbk)//注册一个回调函数,记录回调函数;//F2层
{
cb = cbk;
}
void notify_all_observer(int val)//获取传入回调函数测参数,并将参数传递给回调函数指针cb;字面意思是通知F2,获取到参数//F4,和F2同层//把参数记录下来
{
cb(val);
}
int main()//F1
{
int i=0;
register_observer(callback_func);//F2
int cnt=10;
while(cnt--)
{
cin>>i;
// cout<<&i<<endl;
cout<<i<<endl;
notify_all_observer(i);//F4
}
return 0;
}
在F1
这一层,假如回调函数想传入一个数组,那么可以写成:
typedef struct{void (*callback)(int);}CALLBACK//结构体
int main()//F1
{
int i=0;
CALLBACK cb1;//新建一个结构体
cb1.callback=callback_func;//将回调函数赋值给回调函数的数组
register_observer(cb1);//F2//传入回调函数的数组
int cnt=10;
while(cnt--)
{
cin>>i;
// cout<<&i<<endl;
cout<<i<<endl;
notify_all_observer(i);//F4
}
return 0;
}