目录
0适配器
适配器模式把一个类的接口变换成客户端所期待的另一种接口
从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作
注意:适配器不提供迭代器
以下将介绍几种常用的仿函数适配器
1联结(bind)
通过bind,我们仿函数与参数进行绑定,可实现算法所需的条件判断功能,例如判断小于12的元素时,可使用bind2nd(less(),12),就可以达到目的。
2否定(negate)
这里就是取反的操作,例如not1(bind2nd(less(),12)),就可判断不小于12的元素。
3组合(compose)
当算法的判断条件需要进行一些复杂的数学运算时,即可采用这种适配操作。例如对每个元素v进行(v+2)*3操作,就可表示为compose1(bind2nd(multiplies(),3),bind2nd(plus(),2))。
4一般函数适配器
一般函数可以当做仿函数供STL算法使用,但无配接能力,需要将其包装成仿函数,其原理就是在仿函数的运算符()内执行其所包装的函数即可。
5成员函数适配器
这里将成员函数包装成仿函数,从而可使用成员函数搭配各种泛型算法。当容器内存储的是对象的实体时,需使用mem_fun_ref进行适配;当容器内存储的是对象的指针时,需使用mem_fun进行适配。
分来来源:
7、【C++ STL】适配器:https://www.cnblogs.com/Long-w/p/9830192.html
使用适配器要注意:
1:继承
2:括号重载:一定要是常函数
1适配器概念的引出—联结(bind)函数
打印vector中的元素
vector<int> v;
v.push_back(1);
v.push_back(4);
v.push_back(3);
v.push_back(6);
v.push_back(7);
sort(v.begin(),v.end(),greater<int>());
for_each(v.begin(),v.end(),[](int val){cout<<val<<endl;});
以上是使用函数指针,下面使用函数对象。
函数对象:
class Print
{
public:
void operator()(int v)
{
qDebug()<<v;
}
};
vector<int> v;
v.push_back(1);
v.push_back(4);
v.push_back(3);
v.push_back(6);
v.push_back(7);
sort(v.begin(),v.end(),greater<int>());
for_each(v.begin(),v.end(),Print());
现在有如下要求,打印每个元素的时候,增加100
使用适配器
类
class Print:public binary_function<int,int,void>
{
public:
void operator()(int v,int DeLta) const
{
qDebug()<<"v+DeLta:"<<v+DeLta
<<"v:"<<v
<<"DeLta:"<<DeLta;
}
};
具体操作:
vector<int> v;
v.push_back(1);
v.push_back(4);
v.push_back(3);
v.push_back(6);
v.push_back(7);
sort(v.begin(),v.end(),greater<int>());
int DeLta = 10;
qDebug()<<"增量DeLta"<<DeLta;
qDebug()<<"bind2nd:";
for_each(v.begin(),v.end(),bind2nd(Print(),DeLta));
qDebug()<<"bind1st:";
for_each(v.begin(),v.end(),bind1st(Print(),DeLta));
输出:
使用bind适配器,有四点非常重要
1需要头文件
#include<algorithm>
#include<functional>
2类继承
class Print:public binary_function<int,int,void>
binary_function<参数类型1,参数类型2,返回值类型>
3常函数
重载函数,需要定义为常函数
void operator()(int v,int DeLta) const
4增加适配器
for_each(v.begin(),v.end(),bind2nd(Print(),DeLta));
for_each(v.begin(),v.end(),bind1st(Print(),DeLta));
bind2nd和bind1st有区别,参数的位置和含义不同,所以需要注意,区别看上面的输出
绑定适配器参数必须是函数对象,不能是函数指针
2取反适配器
一元取反:定义函数对象
class GreaterThanFive
{
public:
bool operator()(int v)
{
return v>5;
}
};
具体操作:
vector<int> v;
v.push_back(1);
v.push_back(4);
v.push_back(3);
v.push_back(6);
v.push_back(7);
vector<int>::iterator it = find_if(v.begin(),v.end(),GreaterThanFive());
if(it!=v.end())
{
qDebug()<<"找到了:"<<*it;
}
else
{
qDebug()<<"没有找到";
}
进行取反适配器的使用,增加必要的关键字,继承类
class GreaterThanFive:public unary_function<int,bool>
{
public:
bool operator()(int v) const
{
return v>5;
}
};
具体操作:
vector<int> v;
v.push_back(1);
v.push_back(4);
v.push_back(3);
v.push_back(6);
v.push_back(7);
vector<int>::iterator it = find_if(v.begin(),v.end(),not1(GreaterThanFive()));
if(it!=v.end())
{
qDebug()<<"找到了:"<<*it;
}
else
{
qDebug()<<"没有找到";
}
同样,还可以通过下面的方法,进行操作:使用两个适配器加上内建函数
vector<int>::iterator it = find_if(v.begin(),v.end(),not1(bind2nd(greater<int>(),5)));
使用not适配器,有四点非常重要
1需要头文件
#include<algorithm>
#include<functional>
2类继承
class GreaterThanFive:public unary_function<int,bool>
继承类unary_function<输入数据类型,返回值类型>
3常函数
重载函数,需要定义为常函数
bool operator()(int v) const
4增加适配器
vector<int>::iterator it = find_if(v.begin(),v.end(),not1(GreaterThanFive()));
3函数指针适配器
接口:
void print_function(int v,int DeLta)
{
qDebug()<<"v+DeLta:"<<v+DeLta
<<"v:"<<v
<<"DeLta:"<<DeLta;
}
具体操作:
vector<int> v;
v.push_back(1);
v.push_back(4);
v.push_back(3);
v.push_back(6);
v.push_back(7);
int DeLta = 10;
qDebug()<<"增量DeLta"<<DeLta;
qDebug()<<"bind2nd:";
for_each(v.begin(),v.end(),bind2nd(ptr_fun(print_function),DeLta));
因为绑定适配器(bind)参数必须是函数对象,所以可以把函数指针转化为函数对象。
以下的两个适配器不需要对接口函数进行多余的操作,以下两个适配器主要是将函数指针和成员函数指针变成函数对象。
4成员函数适配器
自定义类型及接口详情
class Person
{
public:
Person(const int num,const QString name)
{
member_num = num;
member_name = name;
}
void showPerson();
int member_num;
QString member_name;
};
void Person::showPerson()
{
qDebug()<<"p.member_name:"<<member_name<<"p.member_num:"<<member_num;
}
具体操作:
Person p1(1,"123");
Person p2(2,"223");
Person p3(3,"323");
Person p4(4,"423");
Person p5(5,"523");
Person p6(6,"623");
vector<Person> v;
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
v.push_back(p6);
for_each(v.begin(),v.end(),mem_fun_ref( Person::showPerson ));
输出:
此处是将成员函数变成函数指针。