一.std::function
std::function 是一个模板类。
作用是对C++中的可调用对象进行包装,包括普通函数、成员函数、模板函数、静态函数、lambda表达式等。
它的最基本的作用是,简化调用的复杂程度,统一调用的方式。
声明方式:
std::function< 返回值类型 ( 参数类型1, 参数类型2, ...) >
二.std::bind
std::bind是一个函数模板,就像是一个函数适配器,接受一个可调用对象,而生成一个新的可调用对象来适配原来的参数列表,该模板返回的是一个std::function对象。用该函数我们也能实现参数顺序的调整和给将指定参数设置成固定值。
function 与 bind 结合后,便成为了 C++ 中类成员函数作为回调函数的一种规范的实现方式。
三.std::placeholders
占位符,c++11中有29个占位符,分别是_1~_29,一般情况下是std::placeholders::_1这样的。占位符的作用就是用来代表参数的,std::placeholders::_1表示的是std::bind得到的std::function对象被调用时,传入的第一个参数,而std::placeholders::_2则是第二个参数。
我们调整std::placeholders::_x在std::bind时的顺序,就可以起到调整参数顺序的作用了。此外,我们也可以在std::bind的时候不用std::placeholders::_x,而直接写成固定的值,这样子调用std::function存储的对象时,对应位置的参数将是固定值。
四.例子
1.普通函数:
头文件
#include <functional>
#include <iostream>
using namespace std;
int Subtract_(int a, int b)
{
std::cout << "Subtract_: " << a << " " << b<< endl;
return a-b;
}
int main()
{
std::function<int(int, int)> func1 = Subtract_;
int ret = func1(1, 2);
cout << ret << endl;
auto f1 = std::bind(Subtract_, std::placeholders::_1, std::placeholders::_2);
auto f2 = std::bind(Subtract_, std::placeholders::_2, std::placeholders::_1);
auto f3 = std::bind(Subtract_, std::placeholders::_1, 100);
cout << f1(30, 66) << endl;
cout << f2(30, 66) << endl;
cout << f3(30, 66) << endl;
return 0;
}
结果
Subtract_: 1 2
-1
Subtract_: 30 66
-36
Subtract_: 66 30
36
Subtract_: 30 100
-70
2.模板函数
template <class T>
T MouldSubtract(T a, T b)
{
return a - b;
}
int main()
{
std::function<double(double, double)> func2 = MouldSubtract<double>;
cout << func2(50, 6.6) << endl;
auto f4 = std::bind(MouldSubtract<double>, std::placeholders::_1, std::placeholders::_2);
auto f5 = std::bind(MouldSubtract<double>, std::placeholders::_2, std::placeholders::_1);
auto f6 = std::bind(MouldSubtract<double>, std::placeholders::_1, 100);
cout << f4(50, 6.6) << endl;
cout << f5(50, 6.6) << endl;
cout << f6(50, 6.6) << endl;
return 0;
}
结果
43.4
3.类普通成员函数
class TestClass
{
public:
int Subtract_(int a, int b)
{
std::cout << "Subtract_: " << a << " " << b << endl;
return a - b;
}
};
int main()
{
TestClass test;
std::function<int(int, int)> func3 = std::bind(&TestClass::Subtract_,&test, std::placeholders::_1, std::placeholders::_2);
cout << func3(30, 66) << endl;
return 0;
}
结果
Subtract_: 30 66
-36
4.类静态成员函数
class TestClass
{
public:
int Subtract_(int a, int b)
{
std::cout << "Subtract_: " << a << " " << b << endl;
return a - b;
}
static int StaticFunc(int a) { return a+100; }
};
int main()
{
std::function<int(int)> func4 = &TestClass::StaticFunc;
cout << func4(36)<< endl;
return 0;
}
结果
136
5.lambda表达式
int main()
{
std::function<int(int,int)> func5 = [](int a, int b) -> int
{
return a - b;
};
cout << func5(36, 100) << endl;
return 0;
}
6.综合使用
#include <functional>
#include <iostream>
using namespace std;
class BindTest
{
public:
BindTest();
void connect(std::function<int(int, int)> func)
{
m_func = func;
}
int addSlot(int a, int b) { return a + b; }
std::function<int(int, int)> m_func;
int signal(int a, int b)
{
int result = m_func(a, b);
//cout <<"signal:"<< result << endl;
return result;
}
};
BindTest::BindTest()
{
// 1. 成员函数作为回调函数,类内调用时,第一个参数需要填this指针。
// connect(std::bind(&BindTest::addSlot, this, placeholders::_1, placeholders::_2));
//3
connect([this](int a,int b)->int{
int result = addSlot(a,b);
cout<<"lambda:"<<result<<endl;
return result;
});
}
int main(int argc, char **argv)
{
BindTest test;
// 2. 外部调用时,将类实例本身的地址作为this指针传入
// test.connect(bind(&BindTest::addSlot, &test, placeholders::_1, placeholders::_2));
//1,2,3
cout << " "<<test.signal(55, 2)<<endl;
// 4
function<int(int,int)> call = bind(&BindTest::addSlot, &test, placeholders::_1, placeholders::_2);
cout<<"fun4:"<<call(55,2)<<endl;
return 0;
}