目录
1、适配器简介
2、函数对象适配器
编辑
3、函数指针作为适配器 ptr_fun
编辑
4、类中的成员函数作为适配器 mem_fun_ref
5、取反适配器
5.1、not1 一元取反适配器
编辑
5.2、not2 二元取反适配器
1、适配器简介
适配器 为算法 提供接口
目前的适配器最多能扩展一个参数,而不是想当然扩展几个就几个
2、函数对象适配器
仿函数作为适配器,就叫做函数对象适配器
适配器详解
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#if 1//第二步:公共继承binary_function 参数萃取
class PrintInt:public binary_function<int,int,void>
{
public://第三步:整个函数加const修饰void operator()(int value, int tmp) const{cout<<"value="<<value<<" tmp="<< tmp<<endl;}
};void test01()
{vector<int> v1;v1.push_back(10);v1.push_back(30);v1.push_back(50);v1.push_back(70);v1.push_back(90);//for_each 提取容器的每个元素//第一步bind2nd 或bind1st//bind2nd将100绑定到第二个参数tmp行 容器的元素在value上for_each(v1.begin(), v1.end(), bind2nd(PrintInt(), 100) );cout<<endl;
}int main(int argc, char *argv[])
{test01();return 0;
}
#else
#endif
for_each 只是负责提取容器中的每一个元素,但是真正输出还是要依靠 仿函数(仿函数根据函数重载或者自定义普通函数提供策略——输出每一个元素还是按要求查找元素等)
仿函数详解
函数对象作为适配器的步骤:
(1)、第一步:使用 bind2nd 或bind1st 绑定第一个或者第二个参数,另一个编译器自动解析传递参数
(2)、第二步:在仿函数上公共继承binary_function 参数萃取
(3)、第三步:整个函数加const修饰
3、函数指针作为适配器 ptr_fun
普通函数作为适配器,因为 在 c 中函数名本身代表的就是函数的入口地址(函数指针:本质是指针变量,但是该变量保存的是函数的入口地址)
但是在 c++ 中我们不能把 函数名 作为函数指针,所以函数名不能成为函数的入口地址,因为 在 c++中 函数的真实入口地址是 函数名+形参+类型,这就是函数重载的来由。所以这个时候就需要将 函数名 使用 ptr_fun 变为函数的入口地址——函数指针,不然函数名充当不了函数指针
然后将多余的参数和 函数指针进行绑定就好
具体代码如下
void myPrintInt(int value, int tmp)
{cout<<"value="<<value<<" tmp="<< tmp<<endl;
}
void test02()
{vector<int> v1;v1.push_back(10);v1.push_back(30);v1.push_back(50);v1.push_back(70);v1.push_back(90);//for_each 提取容器的每个元素for_each(v1.begin(), v1.end(), bind2nd(ptr_fun(myPrintInt),100) );cout<<endl;
}
int main(int argc, char *argv[])
{test01();return 0;
}
4、类中的成员函数作为适配器 mem_fun_ref
&Data::printInt 是取该类中成员函数的入口地址,如果有多个同名函数,那么 &Data::printInt 表示的就是 同名函数的起始位置
class Data
{
public:int data;
public:Data(){}Data(int d){data = d;}void printInt(int tmp){cout<<"value="<<data+tmp<<endl;}
};void test03()
{vector<Data> v1;v1.push_back(Data(10));v1.push_back(Data(30));v1.push_back(Data(50));v1.push_back(Data(70));v1.push_back(Data(90));//for_each 提取容器的每个元素for_each(v1.begin(), v1.end(), bind2nd(mem_fun_ref(&Data::printInt),100) );cout<<endl;
}int main(int argc, char *argv[])
{test03();return 0;
}
5、取反适配器
5.1、not1 一元取反适配器
找出比 30 小的数
void test04()
{vector<int> v1;v1.push_back(10);v1.push_back(30);v1.push_back(50);v1.push_back(70);v1.push_back(90);vector<int>::iterator ret;ret = find_if(v1.begin(), v1.end(), not1(bind2nd(greater<int>(), 30)) );if(ret != v1.end()){cout<<"找到相关数据:"<<*ret<<endl;}
}int main(int argc, char *argv[])
{test03();return 0;
}
5.2、not2 二元取反适配器
lambda 表达式 c++11才支持 []里面啥都不写 lambda不能识别 外部数据 [=] lambda能对 外部数据 读操作 [&] lambda能对 外部数据 读写操作
void test05()
{vector<int> v1;v1.push_back(10);v1.push_back(40);v1.push_back(50);v1.push_back(20);v1.push_back(30);//lambda 表达式 c++11才支持//[]里面啥都不写 lambda不能识别 外部数据//[=] lambda能对 外部数据 读操作//[&] lambda能对 外部数据 读写操作for_each(v1.begin(), v1.end(), [&](int val){cout<<val<<" ";} );cout<<endl;sort(v1.begin(), v1.end(),not2(greater<int>()));for_each(v1.begin(), v1.end(), [&](int val){cout<<val<<" ";} );cout<<endl;
}int main(int argc, char *argv[])
{test05();return 0;
}