可调用实体和仿函数
可调用实体(callable target),C++中包含了几种可调用对象:函数,函数指针,lambda表达式,std::bind创建的对象,以及实现了()操作符的类(仿函数类)
仿函数(functor)又称为函数对象(function object)是一个能行使函数功能的类。
仿函数的语法几乎和我们普通的函数调用一样(函数无状态,仿函数可有状态),作为仿函数的类,必须实现operator()运算符。
struct functor
{
int operator()(int a, int b) {
return a + b;
}
};
struct functor1
{
private:
int base = 1;//状态
public:
int operator()(int a, int b) {
return a + b - base;
}
};
int main()
{
functor f0;
functor1 f1;
cout << f0(1, 2) << ' '<< f1(1, 2) << endl;
}
仿函数是编译器实现lambda的一种方式,编译器通常会把lambda函数转化为一个仿函数对象,lambda可视为仿函数的语法糖
注意:()运算符也是可以重载的
std::function类模板
C++11引入std::function模板类,是一个多用途的函数包裹器,std::function的实例可以存储,拷贝和调用任何可调用的实体,包括全局函数,成员函数,lambda表达式和仿函数以及std::bind()绑定的对象,甚至是成员变量。
std::function统一和简化了相同类型可调用实体的使用方式,使得编码变得简单,它最重要的功能是实现延时调用,保存了指定函数和参数(和std::bind相结合)可以再之后的程序调用过程中调用,这种用法在实际编程中是很常见的
#include<functional>
class funcator {
public:
bool operator()(int a, int b) {
return a > b;
}
};
int main()
{
std:: function<bool()>func = std::bind(funcator(), 3, 2);
cout << func() << endl;
std::function<bool(int)>func1 = std::bind(funcator(), 3, std::placeholders::_1);
cout<<func1(1) << endl;
std::function<bool(int, int)>func2 =
std::bind(funcator(), std::placeholders::_1, std::placeholders::_2);
cout << func2(1, 2);
}
#include<functional>
struct functor
{
int operator()() {
cout << "functor!" << endl;
return 0;
}
};
int testFunc() {
cout << "test!" << endl;
return 0;
}
class Cfunc {
public:
static int StaticFunc() {
cout << "STATIC func!" << endl;
return 0;
}
};
int main()
{
auto lambda = []()->int {
cout << "lambda!" << endl;
return 0;
};
std::function<int()>func = testFunc;//通过std::function保存testFunc
func();
functor f;
func = f;
func();
func = lambda;
func();
func = Cfunc::StaticFunc;
func();
}
std::bind()
std::bind 用来将可调用对象与其参数(也可以是部分参数)一起进行绑定。绑定后可以使用std::function进行保存,并延迟到我们需要的时候调用。
在绑定部分参数的时候,通过使用
std::placeholders来决定空位参数(即未绑定部分参数)的传递顺序
绑定仿函数:
#include<functional>
int calc(int x, int y, int z)
{
cout << "x:" << x << " y: " << y << " z:" << z << endl;
return x + y - z;
}
int main()
{
std::function<int()>func = std::bind(calc, 1, 5, 3);//参数全绑定了,没有多余的参数了
cout << func() << endl;
std::function<int(int)>func1 = std::bind(calc, 1, 5, std::placeholders::_1);//有一个没绑定
cout << func1(2) << endl;
std::function<int(int, int)>func3 =
std::bind(calc, 5, std::placeholders::_1, std::placeholders::_2);
func3(5, 3);//5是剩下的第一个位置,3是第二个位置
}
bind类函数和成员:
#include<functional>
class OBJ
{
public:
int val = 0;//C++允许非静态数据成员声明在所属类内部进行初始化
void output(int x, int y) {
cout << "X " << x << " Y " << y << endl;
}
};
int main()
{
OBJ obj;
std::function<void(int,int)>func = //绑定类中函数
std::bind(&OBJ::output, &obj, std::placeholders::_1, std::placeholders::_2);
function<int&()>func2 = std::bind(&OBJ::val, &obj);//绑定类中数据成员
func(3, 5);
func2() = 123;
cout << obj.val;//输出为123 返回的是a的引用
}