使用类的成员函数来实现回调函数

目标读者:能够理解回调函数的含义


把类的成员函数作为回调函数有三个步骤:

  1. 实现这个成员函数,
  2. 对这个函数进行绑定
  3. 将绑定好的函数指针传给调用函数。

一、添加头文件

#include <functional>

二、typedef一个函数指针类型

这一步是为了方便地得到所需的函数指针变量

typedef std::function<void (int,int)> Fun;//注意void与()之间是空格而不是‘,’

typedef std::function<返回类型 (参数一,参数二)> 函数指针类型名称

三、函数绑定

要想直接将一个类成员函数设置为一个回调函数,而不是使用静态成员函数,需要用到std::bind。

Fun fun = bind(&Test::callback, this,placeholders::_1,placeholders::_2);

回调函数指针类型 函数指针变量 = bind(&类::回调函数, 类指针,参数占位符);


》关于placeholders

placeholders域在这里起到占位符的作用,指明该参数是调用者在使用回调函数时传入的第几个参数。例如placeholders域下的_1、`_2分别代表调用者传入的第一个、第二个参数。

举个例子

读者可以先看完下面回调函数的代码实现后再回过来看这个例子,方便理解。

callback是一个有两个参数的回调函数。实现一个作差的功能。

void Test::callback(int a,int b)
{
    printf("%d - %d = %d", a, b, a - b);
}

绑定时,设置把传入的第2个参数传给变量a,把传入的第1个参数传给变量b。

Fun fun = bind(&Test::callback,this,placeholders::_2,placeholders::_1);

调用者在实际调用时,把值2传给变量a,把值1传给变量b。

fun(1,2);//fun(placeholder::_1, placeholder::_2);

计算结果:

2 - 1 = 1

绑定时不仅可以传入占位符,还可以直接传入变量。例如

int x = 5;
Fun fun = bind(&Test::callback,this,placeholders::_2,x);
fun(1,2);

输出:

2 - 5 = -3

四、代码实例

在这个代码实例中,回调函数,绑定函数和调用函数都放在一个类里面,在实际项目中绑定函数和回调函数一般处在一个类中,而调用函数则存在于其他的类中。


#include <stdio.h>
#include <functional>

using namespace std;

class Test
{
public:
    
    typedef std::function<void (int,int)> Fun;//typedef一个函数指针
    
    void callback(int a,int b)/*回调函数*/
    {
        printf("%d+%d = %d",a,b,a+b);
    }
    
    void bind()/*绑定*/
    {
        Fun fun = bind(&Test::callback, this,placeholders::_1,placeholders::_2);
        call(1, fun);
    }
    void call(int a,Fun f)/*调用者*/
    {
        f(a,2);
    }
    
};


int main()
{
    
    Test test;
    test.bind();
    
    return 0;
}

输出结果:

1+2=3

五、参考资料:

1、std::function与std::bind 函数指针 (实现回调函数的不同方式)

2、cplusplus:std::placeholders (placeholders的用法)

作者:唐衣可俊
出处:http://www.cnblogs.com/tangyikejun/
版权:本文版权归作者本人所有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任