记得当初学习C++的时候,老师就说,回调函数是我们自己定义,系统自动调用的函数。看起来好神秘哦,它到底是怎么实现自动调用的呢,看了下面的介绍,明白其原理后,也觉得没有什么了不起的。
在介绍回调函数之前,要知道什么是函数指针。
我们知道函数放在内存的代码区域内,它们同样有地址,它们的地址就是函数的名称。
例如函数:int test(int a);
那么它的函数地址就是test;
我们定义一个指向函数的指针用如下形式:
typedef int (*p) (int a);
p pFun ;
pFun=test;
pFun(10); //相当于调用 test(10);
(1)、什么回调函数呢?
简而言之,回调函数就是一个通过函数指针调用的函数,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。
(2)、使用回调函数有什么好处?
因为回调函数可以把调用者与被调用者分开,调用者不用关心谁是被调用者。它只需要知道存在一个具有什么样返回值、什么参数类型、参数的数量的特定原型函数就可以了。
(3)、回调函数的标准调用约定
我们看见的回调函数通常以 __stdcall标识。为什么叫标准约定呢?因为所有的win32 API都使用它。标准调用约定的函数在他们返回到调用者之前,都会从堆栈中移除掉参数,这也是pascal的标准约定。
调用约定 _stdcall 以每个函数的名称修饰通过前添加一个下划线字符 (如同 _cdecl 约定) 和追加一个位于"@"符号和十进制表示形式的所需的堆栈空间的字节数。 每个参数扩展为四个字节的倍数。
下面的代码示例演示如何生成和支持标准调用约定所调用的函数中调用的函数的代码。
int _stdcall StdFunc(int a, int b); calling function called function ------------------------------------------- push b _StdFunc@8 PROC NEAR push a . call _StdFunc@8 . . . . RET 8 . _StdFunc@8 ENDP
(4)、回调函数的使用
int __stdcall g(int a,int b); int _tmain(int argc, _TCHAR* argv[]) { //回调函数的调用 typedef int(__stdcall *p)(int a,int b); p pFun; pFun=g; cout<<"回调函数的值:"<<pFun(20,30)<<endl; return 0; } //回调函数的定义 int __stdcall g(int a,int b) { return (a+b)*(b-a); }