针对标题的两种情况,使用起来有一定的特殊性,特此记录下。
至于其他常规的bind使用方法,网上有很多文章有介绍,也可以看这篇文章。
标题的两种情况:
情况一:
这个例子用了两个知识:
第一,关于std::function的使用方法,这是个函数包装器,返回一个可调用对象。
第二,mf = &C::menfunc
, 这个是对类的普通成员函数(另外两种是,类静态函数、虚成员函数,用法其实存在差异的)取地址,这里要说明的是:&C::menfunc
的返回类型是,void (C::*)(int , int)
. 所以在语义上(注意不是用法,用法是有差异),mf = &C::menfunc
==void (C::*mf)(int , int) = &C::menfunc
.
事实上,void (C::*mf)(int , int) = &C::menfunc
,的调用方法是:C c; c.*mf(42, 77)
。这种调用方法与使用std::function的实现方式,其实从底层实现看是一致的,因为成员函数需要传递一个this指针给作为自己的第一参数,也就是编译器会将c.*mf(42, 77)
转换为*mf(&c, 42, 77)
。
std::function<void(const C&, int, int)>只是上面实现的一种包装形式。
总结上面的用法可以发现,利用bind的绑定未初始化类的成员函数是时,则在调用这个可调用对象时需要另外传递一个对象给其作为参数,这本质上与在绑定时就提供一个对象(这是我们常见的bind类成员函数的用法)是一致的,早提供对象或晚提供对象其实无所谓,二者都是只是在程序真正调用由bind绑定的可调用对象时作为参数传递给函数罢了。
情况二(标黄部分,其他的属于常规bind的用法):
我们将类重载运算符()
后的成员函数称之为:函数对象,那么函数对象用在bind有什么特别的地方呢?
第一,函数对象的调用非常友好,当我们实例化一个类的对象后,对对象调用
()
运算符就可以实现其函数功能:C c; c(42, 17);
第二,函数对象在使用bind的绑定时就会带来普通成员函数不一样的用法,差异就在,当绑定函数对象时,我们直接传递对象就行,假如有auto f4 = bind(C(), _1, _2);
,则f4(42, 17);
就能实现调用函数对象的实现。
看下面的例子直接学习用法即可,用法也很直观简单,不得不说,C++11的bind的真是太牛叉了!
#include <iostream>
#include <functional>
#include <typeinfo>
using namespace std;
using namespace placeholders;
class C {
public:
C() {
}
C(int x) {
a = x;
}
int operator () (int x, int y) const {
return a + x + y;
}
int fun (int x) {
a = x;
return a;
}
int a = 1;
};
int main () {
C c;
auto f1 = bind(&C::fun, C(), _1);
cout << f1(2) << endl;
auto f2 = bind(f1, 3);
cout << f2() << endl;
auto f3 = bind(&C::fun, _1, _2);
cout << f3(C(), 4) << endl;
auto f4 = bind(C(), _1, _2);
cout << f4(2, 2) << endl;
auto f5 = bind(c, _1, _2);
cout << f5(2, 2) << endl;
}
输出: