关于回调函数
回调函数在百度百科的讲解是这样的
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
通俗的理解 就是 有两个函数A,B,在函数B中有指向A函数的指针,函数B可以通过A函数的指针来调用A函数。
下面分三种情况来讲回调函数
1 回调函数是全局函数
这种情况比较简单了 直接看代码
typedef void(*pFun)(int);
void fun1(int a)
{
cout << a << endl;
}
void fun2(pFun pf,int m)
{
pf(m);
}
int main()
{
pFun p;
p = fun1;
fun2(p, 10);
return 0;
}
打印的结果是 10
程序第一句 定义了一个函数指针,该函数接收1个int行形参,返回值为空,在main函数中,第一句定义一个函数指针类型的p,p可以指向一个接收一个int类型的参数,返回值为空的函数,第二句把 fun1函数赋值给p,第三句把p做为参数传递给fun2,在fun2中就可以调用fun1了。
在C++中 大多数情况我们用到的都是类,那么在类中 类的非静态成员函数可以可以作为回调函数呢 答案是不可以的 ,因为普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递this指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数却-有不同的数据成员。由于this指针的作用,使得将一个成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数调用失败,要解决这个问题有两种方法
第一种 既然回调函数不能有this指针 那么我们可以 把回调函数声明为静态的 代码如下
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef void(*pFun)(int);
class B
{
public:
B()
{
pf = NULL;
}
void Show(int s)
{
pf(s);
}
void SetPf(pFun back)
{
if (back == NULL)
return;
this->pf = back;
}
private:
pFun pf;//声明一个函数指针
};
class A
{
public:
static void BackShow(int m)
{
cout << "回调函数被调用:" <<m<< endl;
}
};
int main()
{
B *b = new B();
b->SetPf(A::BackShow);
b->Show(10);
return 0;
}
输出结果为: 回调函数被调用:10
我们把A的静态成员函数地址 传递给b的pf,然后调用b的pf自然就调用的A的BackSHow方法了 ,但是在实际应用中,回调函数在大部分情况是需要访问类成员变量或者成员函数做一些事情的,如果把回调函数设为static,这样就需要类的成员变量和成员方法都设置成static ,不和实际情况,解决方法是在类的静态成员做为回调函数的时候,给该回调函数传递一个this指针 代码如下
<pre name="code" class="cpp">#include "stdafx.h"
#include <iostream>
using namespace std;
typedef void(*pFun)(void*,int);
class A
{
public:
static void backcall(void* a, int m)
{
A *af = (A*)a;
af->show(m);
}
void show(int m)
{
cout << "A中show函数被调用:" << m << endl;
}
};
class B
{
public:
B()
{
a = NULL;
pf = NULL;
}
void CalledA(int m)
{
pf(a, m);
}
void SetA(A *a)
{
this->a = a;
}
void SetPf(pFun pf)
{
this->pf = pf;
}
private:
A *a;
pFun pf;
};
int main()
{
A *a = new A();
B *b = new B();
b->SetA(a);
b->SetPf(A::backcall);
b->CalledA(10);
delete a;
delete b;
}
在调用回调函数的时候,传递给他一个A的对象就可以了访问非静态成员或方法了 ,那么有时候 我们不想把回调函数设为static 怎么办呢,代码如下
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef void(*pFun)(int);
class A
{
public:
friend void BackCall(int m)
{
cout << "友元函数被调用" << m << endl;
}
};
void show(pFun f)
{
f(10);
}
int main()
{
show(BackCall);
}