boost::function 与 boost::bind 用法详解

本文boost::function部分转自:https://blog.csdn.net/huangjh2017/article/details/71124827

 boost::bind部分转自:https://yq.aliyun.com/articles/33187

boost::function

是一个函数对象的“容器”,概念上像是C/C++中函数指针类型的泛化,是一种“智能函数指针”。它以对象的形式封装了原始的函数指针或函数对象,能够容纳任意符合函数签名的可调用对象。因此,它可以被用于回调机制,暂时保管函数或函数对象,在之后需要的时机在调用,使回调机制拥有更多的弹性。

既然boost::function经常被用于回调机制,我们就先看看什么是回调函数吧.

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

我们先来看看c/c++中函数指针在普通函数和类成员函数的使用吧!

#include 
 
using namespace std;
 
class CEventQuery;
 
typedef bool (*CommonFuncPoint)(void);                //普通函数指针
typedef bool (CEventQuery::*ClassFuncPoint)(int);    //类成员函数指针
 
bool CommonFunc(void)
{
    //这是个回调函数,当特定的事件或条件发生
    //的时候,会被调用。
    cout << "CallBackFunc Common Function Call!" << endl;
    //这里会有特定事件或条件发生时需要处理的事
    //....
    return true;
}
 
class CEventQuery
{
public:
    CEventQuery(CommonFuncPoint eventFunc)
        :m_Event(eventFunc)
    {
    
    }
 
    ~CEventQuery()
    {
    
    }
 
    void Query(void)
    {
        //这里会检测某个事件或条件的发生        
        //比方说这里查询到了事件发生或条件的改变,那么就回调处理函数
        m_Event();
    }
 
    bool DoSomething(int iValue)
    {
        cout << "Class Function DoSomething Parament : " << iValue << endl;
        return true;
    }
 
private:
    CommonFuncPoint m_Event;
};
 
int main(void)
{
    CEventQuery tEventQuery(CommonFunc);
 
    tEventQuery.Query();
 
    ClassFuncPoint ClassFunc1 = &CEventQuery::DoSomething;
    (tEventQuery.*ClassFunc1)(10);
 
    tEventQuery.DoSomething(20);
 
    return 0;
}

运行结果如下所示:

CallBackFunc Common Function Call!
Class Function DoSomething Parament : 10
Class Function DoSomething Parament : 20


不足的地方是,这种方式的调用只适用于函数指针,不适用于非函数指针(比如函数对象),这就是局限性。


与之前使用函数指针不同,function就像是一个函数的容器,也可以把function想象成一个泛化的函数指针,只要符合它声明中的函数类型,任何普通函数,成员函数,函数对象都可以存储在function对象中,然后在任何需要的时候被调用。

boost::function能够代替函数指针,并且能能接受函数或函数对象,增加了程序的灵活性。当然,带来好处的同时,也必然有弊端。boost::function相比函数指针来说体积稍大一点,速度上稍慢一点。不过相比于boost::function带来的灵活性相比速度和体积就显得举足轻重了。

查看Boost官方文档,Boost.Function 有两种形式:首选形式和便携式形式, 其语法如下:

首选语法    便携式语法

boost::function
 f;
boost::function2
 f;

这两种形式等价,大家可以选择一种自己喜欢使用的形式即可(有一些较老的编译器不支持便携式)。
作为示范,我们的例子展示了:普通函数、类成员函数、函数对象的使用。当然function可以配合bind使用,存储bind表达式的结果,使bind可以被多次调用。目前没用到,下次再补充。

#include 
#include 
 
using namespace std;
 
template
class CFuncDemo
{
public:
    CFuncDemo(int iValue)
        :m_iValue(iValue)
    {
    }
 
    template
    void acceptFunc(CallBackFunc Func)
    {
        m_Func = Func;
    }
 
    void CommonResult()
    {
        m_Func(m_iValue);
    }
 
    template
    void ClassMemberResult(T &t)
    {
        m_Func(t, m_iValue);
    }
 
    void FuncObjResult()
    {
        m_Func(m_iValue);
    }
 
private:
    Func m_Func;
    int m_iValue;
};
 
//普通函数
void CommonFunc(int iValue)
{
    cout << "CallBack Common Function" << endl;
    cout << "2 * iValue = " << 2 * iValue << endl;
}
 
//这个类有个成员函数完成类似的功能
class CMultiple
{
public:
    void ClassFunc(int iValue)
    {
        cout << "CallBack Class Member Function" << endl;
        cout << "3 * iValue = " << 3 * iValue << endl;
    }
};
 
//这里有个函数对象同样也完成对应的功能
class CFuncObj
{
public:
    void operator()(int iValue)
    {
        cout << "CallBack Function Object" << endl;
        cout << "4 * iValue = " << 4 * iValue << endl;
    }
};
 
int main(void)
{
    //作为示范的测试用例,这里我们展示了:普通函数、类成员函数、函数对象的使用
 
    //普通函数
    CFuncDemo> tFuncCommon(10);
    tFuncCommon.acceptFunc(CommonFunc);
    tFuncCommon.CommonResult();
 
    //类成员函数
    CMultiple tMember;
    CFuncDemo> tFuncClassMember(10);
    tFuncClassMember.acceptFunc(&CMultiple::ClassFunc);
    tFuncClassMember.ClassMemberResult(tMember);
 
    //函数对象
    CFuncObj tObj;
    CFuncDemo> tFuncObj(10);
    //tFuncObj.acceptFunc(tObj);
    //function使用拷贝语义保存参数,使用ref它允许以引用的方式传递参数
    tFuncObj.acceptFunc(boost::ref(tObj));
    tFuncObj.FuncObjResult();
 
    return 0;
}

下面是测试结果:

CallBack Common Function
2 * iValue = 20
CallBack Class Member Function
3 * iValue = 30
CallBack Function Object
4 * iValue = 40

boost::bind

#include 
#include 
#include 
 
using namespace boost;
using namespace std;
 
int f(int a, int b)
{
    return a + b;
}
 
int g(int a, int b, int c)
{
    return a + b * c;
}
 
class Point
{
public:
    Point(int x, int y) : _x(x), _y(y) {}
    void print(const char *msg) {
        cout << msg << "x=" << _x << ", y=" << _y << endl;
    }
private:
    int _x, _y;
};
 
int main()
{
    //! f 有多少个参数,f 后面就要跟多少个参数。如果不明确的,用占位符
    cout << bind(f, 2, 3)() << endl;    // ==> f(2, 3)
    cout << bind(f, 12, _1) (5) << endl;   // ==> f(12, 5),其中参数b为不明确参数
    cout << bind(g, _2, _1, 3) (3, 5) << endl;  // ==> g(5, 3, 3) 注意顺序
 
    Point p(11, 34);
    Point &rp = p;
    Point *pp = &p;
 
    bind(&Point::print, p, "Point: ") ();
    //   ^              ^
    // 注意,为表示Point::print为成员函数,成员函数前面要加&区分。
    // 对象可以为实例、引用、指针
    bind(&Point::print, rp, "Reference: ") ();  //! 引用
    bind(&Point::print, pp, _1) ("Pointer: ");  //! 指针
    bind(&Point::print, _1, _2) (p, "As parameter: ");  //! 对象也可以用占位符暂时代替
 
    //! function的类型定义与需要的参数有关
    function func0 = bind(&Point::print, p, "func0: ");
    function func1 = bind(&Point::print, pp, _1);
 
    func0();    //! function对象的调用
    func1("func1: ");
 
    return 0;
}

一般情况下,bind 与 function 配合使用。

bind与function还可以将类型完成不同的函数(成员函数与非成员函数)包装成统一的函数调用接口。如下示例:

#include 
#include 
#include 
#include 
 
using namespace boost;
using namespace std;
 
class Point
{
public:
    Point(int x, int y) : _x(x), _y(y) {}
    void print(string msg) {
        cout << msg << "x=" << _x << ", y=" << _y << endl;
    }
private:
    int _x, _y;
};
 
class Person
{
public:
    Person(string name, int age) : _name(name), _age(age) {}
    void sayHello() {
        cout << "Hello, my name is " << _name << ", my age is : " << _age << endl;
    }
private:
    string _name;
    int _age;
};
 
void printSum(int limit)
{
    int sum = 0;
    for (int i = 0; i < limit; ++i) {
        sum += i;
    }
    cout << "sum = " << sum << endl;
}
 
void doAll(vector > &funcs)
{
    for (size_t i = 0; i < funcs.size(); ++i) {
        funcs[i] ();
    }
}
 
int main()
{
    vector > funcList;
 
    Person john("John", 23);
    funcList.push_back(bind(&Person::sayHello, john));
 
    Point p1(23, 19);
    funcList.push_back(bind(&Point::print, p1, "Point: "));
 
    funcList.push_back(bind(printSum, 20));
 
    doAll(funcList);
    return 0;
}

 

你可能感兴趣的:(C++,boost)