一直以来都被回调函数的定义给整蒙了。最近又仔细学了会,感觉回调函数,我认为就是将一个函数指针A作为参数传入另外一个函数B,然后在函数B中调用函数A。
具体先看一个简单的例子:
#include
void printWelcome(int len)
{
printf("welcome -- %d\n", len);
}
void printGoodbye(int len)
{
printf("byebye-- %d\n", len);
}
void callback(int times, void (* print)(int))
{
int i;
for (i = 0; i < times; ++i)
{
print(i);
}
printf("\n welcome or byebye !\n");
}
void main(void)
{
callback(10, printWelcome);
callback(10, printGoodbye);
}
我认为这就算一个简单的回调。在callback中使用print函数指针作为参数,然后在函数中调用print相关的函数,这就属于回调。
当然,这只是一个很简单的例子。在各种c++中,回调可是牛逼闪闪。
在c++中,一般需要使用类进行函数的封装。但是在调用一般的类的成员函数时,使用类的成员调用时,需要传递this指针
《深入探索C++对象模型》中提到成员函数时,当成员函数不是静态的,虚函数,那么我们有以下结论:
(1) &类名::函数名 获取的是成员函数的实际地址;
(2) 对于函数x来讲obj.x()编译器转化后表现为x(&obj),&obj作为this指针传入;
(3) 无法通过强制类型转换在类成员函数指针与其外形几乎一样的普通函数指针之间进行有效的转换。
所以,要在回调函数中传入一个类的普通成员函数时,this指针无处安放,使得回调函数比较复杂。
#include
#include
using namespace std;
using namespace std::placeholders;
typedef std::function Fun;
class B{
public:
void call(int a,Fun f)
{
f(a,2);
}
};
class Test{
public:
void callback(int a,int b)
{
cout<
上面的程序中,Test类中的bind函数调用B类中的call函数,b中的call函数又反过来回调Test类中的callback函数。记住function和bind都是c++11标准函数,编译的时候要加-std=c++11。
//g是一个有两个参数的可调用对象
auto g=bind(f,a,b,_2,c,_1);
//其中f是具有5个参数的函数
//当我们调用g(x,y)时,实际调用的是f(a,b,y,c,x)
在这个示例中,我们可能要调用f函数,并传入5个参数,但是我们现在调用g(x,y),只要传入两个参数,同样能达到这个效果。当然,我费这么多事其实肯定不是为了省几个参数,主要还是为了将一个函数转化成一个可以作为回调的函数指针,可以看成是原函数指针的别名。
Fun fun=std::bind(&Test::callback,this,_1,_2);
其中bind用于绑定一个Test类的callback函数,它有两个参数,在这里,因为它是一个类成员函数,中间传入一个this指针,另外两个_1和_2则是它的两个参数。bind返回一个函数指针,将它赋给fun,fun作为一个函数容器,容纳bind函数返回的临时函数指针。 这样就成功的将fun作为一个函数参数的别名,可以用于传给回调函数了。
#include
#include
using namespace std;
typedef std::function fp;
void g_fun()
{
cout<<"g_fun()"< fpi;
//对于参数要使用占位符 std::placeholders::_1
fpi f=std::bind(&A::A_fun_int,this,std::placeholders::_1);
f(5);
}
};
int main()
{
//绑定到全局函数
fp f2=fp(&g_fun);
f2();
//绑定到类静态成员函数
fp f1=fp(&A::A_fun_static);
f1();
A().init();
A().init2();
return 0;
}