1 仿函数
仿函数:类模仿函数调用行为,实质是无名对象调用重载()的函数
一般仿函数用于排序准则或一些算法准则
标准库中的仿函数
算术类 关系类 逻辑类
#include<iostream>
#include<functional>
using namespace std;
//仿函数 类模仿函数的调用行为
class Sum
{
public:
int operator()(int a, int b)
{
return a + b;;
}
int operator()(int a, int b, int c)
{
return a + b + c;
}
protected:
};
int main()
{
Sum s;
cout << "显示调用重载函数" << s.operator()(1, 3) << endl;
cout << "隐式调用" << s(1, 3) << endl;
//用{} ()帮助编译器解析,不加()或 {}解析为构造函数
//类模仿函数的调用行为--仿函数
cout << "无名调用" << Sum()(1, 3) << endl;
cout << "无名调用" << Sum{}(1, 3, 5) << endl;
//标准库中算术 + - *
cout << plus<int>{}(1, 3) << endl;
cout << minus<int>{}(1, 3) << endl;
cout << multiplies<int>{}(1, 3) << endl;
//== <=
cout << equal_to<int>{}(1, 3) << endl;
cout << less_equal<int>{}(1, 3) << endl;
//逻辑 与 非
cout << endl << logical_and<int>()(1, 3) << endl;
cout << logical_or<int>()(1, 3) << endl;
cout << logical_not<int>()(1) << endl;
return 0;
}
2 函数适配器
用来绑定函数调用时的参数,让函数适应其他的调用的用法。
利用bind函数
bind()函数需要函数指针,占位符
占位符 std::placeholders::_1 ; 标准库总共有20个这样的占位符,表示这个参数依照原样传参。未使用占位符的地方,如果绑定了固定值,则在函数调用时可以省略这个参数,如果依据传参则使用绑定的值。
可以搭配greater less lambad等使用
利用占位符可以形成不同的调用形态
#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
int Max(int a, int b)
{
return a > b ? a : b;
}
void print(int(*pMax)(int, int), int a, int b)
{
cout << pMax(a,b)<<endl;
}
void printData(int a, string b, double c)
{
cout << "调用函数 "<< endl;
}
class Test
{
public:
void print(int a, int b)
{
cout << a << " " << b << endl;
}
static void printSta(int a, int b)
{
cout << "static:"<<a <<" "<< b << endl;
}
protected:
};
//绑定类中的函数
void testclassFunc()
{
Test test;
auto pfun = bind(&Test::print,&test,std::placeholders::_1,22);
pfun(43);
auto pfun2 = bind(Test::printSta,std::placeholders::_1,33);
pfun2(35);
}
// 通过占位符调整参数位置,形成不同的调用形态
void test()
{
auto testFunc = bind(printData, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
printData(1,"hahada",9.99);
//testFunc(1,"hahada",9.99);绑定之后 调用时错误的
testFunc(9.99,1,"hahha");//对的 函数调用时的占位符表示原函数中参数要去的位置
// 原函数参数 int string double
// 调用的占位符 2 3 1
// 表示原来的int 去2号为,string去3号为,double去1号位
}
int main()
{
cout << Max(1, 3) << endl;
//基本用法
//std::placeholders::_1 第一个参数占位符 ,使用时表示第一个参数按原样传参,标准库提供了20个占位符
//bind() 绑定函数
auto pMax = bind(Max,std::placeholders::_1,100); //第二个参数固定为100
cout << pMax(12) << endl;//原本Max函数需要两个参数,现在绑定之后只需要传一个参数即可
//只是增加调用行为 并没有改变函数指针类型
cout << pMax(12, 34) << endl; //绑定之后传第二个参数无效
vector<int> data = {111,22,333,40,54,5,56};
cout << count_if(data.begin(),data.end(),bind(greater<int>(),std::placeholders::_1,40))<<endl;
// count_if 条件统计函数,在指定区间内满足条件的个数
//bind() 这里绑定的是greater函数,筛选>40的个数
cout << count_if(data.begin(), data.end(), [](int a) { return a > 60; }) << endl;
test();
testclassFunc();
return 0;
}
3 函数包装器
函数包装器:就是把函数指针包装成一个对象,利用对象调用函数。
一旦函数指针被函数包装器包装了,那这个函数包装器的对象可以直接替换函数指针的用法去调用函数
function<函数返回值类型(参数类型)>
#include<iostream>
#include<functional>
#include<string>
using namespace std;
int Max(int a, int b)
{
cout << "包装普通函数" << endl;
return a > b ? a : b;
}
class MM
{
public:
void print(int a)
{
cout << "类中的成员函数" << a << endl;
}
static void printStatic(int b)
{
cout << "静态函数" << b << endl;
}
friend ostream& operator<<(ostream& out, MM object)
{
out << object << endl;
return out;
}
protected:
};
class Test
{
public:
void operator()(string str)
{
cout << "包装仿函数:" << endl;
}
protected:
};
void printData(int a, MM mm, string str)
{
cout << "测试包装bind" << endl;
}
void testFunBind()
{
function<void(MM, string, int)> pB = bind(printData, std::placeholders::_3, std::placeholders::_1, std::placeholders::_2);
pB(MM(),"lalla",22);
}
int main()
{
//包装普通函数
function<int(int, int)> funMax(Max); // funMax 定义的对象, Max是函数指针
cout << funMax(1,22);
//也可以用以下方式
function<int(int, int)> funMax2 = Max;
//包装类中的 函数
cout << endl;
MM mm;
//包装静态函数
function<void(int)> funS(MM::printStatic);
funS(2);
//包装成员函数 利用bind
function<void(int)> funP(bind(&MM::print, &mm, std::placeholders::_1));
funP(222);
//包装仿函数
Test test;
function<void(string)> pT = test;
pT("lalal");
//包装bind
testFunBind();
return 0;
}