C++ 11 std::function和std::bind使用详解

2020-02-20 12:01:05王旭

(5)类的this可以通过对象或者指针来绑定

std::function

它是函数、函数对象、函数指针、和成员函数的包装器,可以容纳任何类型的函数对象,函数指针,引用函数,成员函数的指针。
以统一的方式处理函数、函数对象、函数指针、和成员函数。允许保存和延迟执行函数。

函数和成员函数作为function
function是一个拥有任何可以以"(...)"符号进行调用的值的类型。特别地,bind的返回结果可以赋值给function类型。function十分易于使用。(译注:更直观地,可以把function看成是一种表示函数的数据类型,就像函数对象一样。只不过普通的数据类型表示的是数据,function表示的是函数这个抽象概念。)例如:

typedef std::function<float (int x, int y)> f ;// 构造一个函数对象,它能表示的是一个返回值为float,两个参数为int,int的函数 
struct int_div {    // 构造一个可以使用"()"进行调用的函数对象类型 
  float operator() (int x, int y) const { return ((float)x)/y; };
};

void HelloWorld::testing()
{
  f f1= int_div();          // 赋值 
  auto result3 = f1( 10, 2);
}

成员函数可被看做是带有额外参数的自由函数:

struct int_div {    // 构造一个可以使用"()"进行调用的函数对象类型 
  float operator() (int x, int y) const { return ((float)x)/y; };
  int int_div_fun( int x ){ return x; };
};
typedef std::function<int (int_div*, int)> f_2;

bool HelloWorld::init()
{
  f_2 f2 = std::mem_fn(&int_div::int_div_fun);      // 指向成员函数

  int_div int_div_object;
  int v = f2(&int_div_object, 5); // 在对象x上用参数5调用X::foo()
  std::function<int (int)> ff = std::bind( f2, &int_div_object, std::placeholders::_1);  // f的第一个参数是&x
  v = ff(5);        // 调用x.foo(5)


}

ps:被vs2012的bug给坑了。因为看网上的代码于是刚开始第9行是这么写的:f_2 f2 = &int_div::int_div_fun;

然后就报错误:Error 1 error C2664: 'std::_Func_class<_Ret,_V0_t,_V1_t>::_Set' : cannot convert parameter 1 from '_Myimpl *' to 'std::_Func_base<_Rx,_V0_t,_V1_t> *'

查了一下,vs2010没有这个编译错误,但是2012有。2012必须得加上std::mem_fn才能编译。

可以用function取代函数指针。因为它可以保存函数延迟执行,所以比较适合作为回调函数,也可以把它看做类似于c#中特殊的委托,只有一个成员的委托。

struct int_div { // 构造一个可以使用"()"进行调用的函数对象类型 
  float operator() (int x, int y) const { return ((float)x)/y; };
  int int_div_fun( int x ){ return x; };

  int_div( std::function<void()>& f ):m_callback(f){};
  void Notify()
  {
    m_callback();
  }
  std::function<void()> m_callback;
};