C++ 函数对象与bind
要点
函数对象
重载了()的对象,和函数一个概念,但用对象来管理,可以有自己的状态什么的。
是用来代替 c 里的函数指针的.
准确的讲叫指向函数的泛化指针
.
函数对象可以用
函数指针;
另1个相同函数调用的函数对象;
lambda;
如果类里需要持有 1 个函数指针,就可以用函数对象:
typedef std::function<int(const Sth & a)> callFunction;
class A{
private:
callFunction cb;
}
lambda
lambda 可以等价为一个函数对象:
struct Compare {
int operator()(cosnt int a, const int b){
return a >= b;
}
}
sort(begin(w),end(w),[](const int a, const int b){return a>=b;});
//和上面一致
sort(begin(w),end(w),Compare());
标准库函数对象
#include<functional>
.
算术、运算、和逻辑,用在 algorithm 里,免得自己写:
sort(begin(w),end(w),greater<string>());
如果需要自己版本的标准库函数对象,就特例化1个:
template<> greater<A>::operator() {
return A.val > A.val;
}
例子:
#include <iostream>
#include <functional>
void test_3(int a, int b, int c){
std::cout << a << " Bind " << b << std::endl;
}
void test(int a, int b){
std::cout << a << " Global function " << b << std::endl;
}
struct A {
void test(int a, int b){
std::cout << a << " Member Function " << b << std::endl;
}
};
int main()
{
std::function<void (int,int)> f1 = test;
std::function<void (int,int)> f2(test);
std::function<void (int,int)> f3 = [](int a, int b){
std::cout << a << " Lamba Function " << b << std::endl;
return 100;
};
A a;
//需要bind配合,返回1个function obj;
using namespace std::placeholders;
//bind函数
std::function<void (int,int)> f4 = std::bind(test_3,_1,_2,0);
//bind成员函数
std::function<void (int,int)> f5 = std::bind(&A::test,a,_1,_2);
f1(0,0);
f2(0,0);
f3(0,0);
f4(0,0);
f5(0,0);
return 0;
}
可调用对象与 function 类模板
可调用对象: 函数、函数指针、函数对象、lamdba、bind 返回的函数对象.
不同的可调用对象共享相同的调用形式,如int (int,int)
;
可能希望建立个函数表,可以把不同调用对象都放进来:
map<string ,int(*)(int,int)> function_maps;
function_maps.insert({"+", add});
mod = Mod(); //函数对象
//添加失败,因为类型不匹配
function_maps.insert({"%", mod}) ;
为解决上面的类型不兼容,但是调用形式又相同的情况,c++11 定义了 function 模板类.
function<int(int,int)> f;
f1 = add;
f2 = divide();
f3 = [](int i,int j){return i / j};
map<string, function<int(int,int)>) new_maps;//真正好用的函数表map
//初始化
new_maps["+"] = add;
new_maps["%"] = divide();
new_maps["/"] = f3;
//使用
new_maps["+"](1,2); //1+2