适配器:
适配器相当于提供了一个接口,使得某些不适用于特定对象的方法可以被该对象所用,适配器形象的功能图解如所示,图中,容器或函数对象无法直接应用于算法,因此,必须有一种中间过渡机制来实现两者的匹配,这就是适配器,本质上,适配器是使一事物的行为类似于另一事物的行为的一种机制。
容器适配器:
1、容器适配器可以看作是对容器的封装,使其具有某些特殊的功能。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现,只是发生了接口转换而已。标准库提供了三种序列容器适配器:
stack(deque,list)、
queue(deque,list)、
priority_queue(vector, deque)。
2、所有适配器都定义了两个构造函数:默认构造函数用于创建空对象,而带一个容器参数的构造函数将参数容器的副本作为其基础值。
3、默认的stack和queue都基于deque容器实现,而priority_queue则在vector容器上实现。在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型参数,可覆盖其关联的基础容器类型。例如,下述代码创建的ob栈是基于vector实现的:stack<int, vector<int> > ob;
#include<iostream>
#include<vector>
#include<stack>
#include<string>
using namespace std;
int main()
{
stack<int,vector<int> > ob1; //使用vector取代其默认的deque做为stack的实现基础
cout<<ob1.size()<<endl;
for(int i=0;i!=10;++i)
{
ob1.push(i);
}
cout<<ob1.size()<<endl;
cout<<ob1.top()<<endl;
ob1.pop();
cout<<ob1.top()<<endl;
cout<<"********"<<endl;
|
stack<string,vector<string> > ob2;
for(char i=65;i!=91;++i)
{
string tmp = string(1,i);
ob2.push(tmp);
}
cout<<ob2.top()<<endl;
ob2.pop();
cout<<ob2.top()<<endl;
return 0;
}
|
#include <iostream>
#include <queue>
using namespace std;
int main()
{
queue<int> queInt;
for(int idx = 0;idx < 10; ++idx)
{
queInt.push(idx); //入队
cout<< queInt.back() <<" 入队"<<endl; //取队尾元素
}
cout<<queInt.size()<<" 个元素已经入队"<<endl;
while(!queInt.empty())
{
cout<< queInt.front() <<" 出队"<<endl; //取队头元素
queInt.pop(); //出队
}
cout<< queInt.size()<<endl;
return 0;
}
|
#include <iostream>
#include <queue>
using namespace std;
//采用的是"堆排序"进行元素的调整,默认情况下,比较函数是"<" 符号,堆顶的元素要与新进来的元素进行比较,如果为true,则将堆顶的元素放到堆底,新进来的元素放到堆顶;然后进行堆的调整
//出队从大到小
int main()
{
int arr[10]={0,1,3,2,5,6,9,8,7,4};
priority_queue<int> pqueInt;
for(int idx = 0;idx != 10; ++idx)
{
pqueInt.push(arr[idx]);
cout<< pqueInt.top() <<"是优先级别最高的"<<endl;
}
while(!pqueInt.empty())
{
cout<< pqueInt.top() <<"出队"<<endl;
pqueInt.pop();
}
return 0;
}
|
迭代器适配器:
1、流迭代器也是迭代器适配器,此外,还包括反向迭代器和插入迭代器。和使用流迭代器一样,使用反向和插入迭代器都必须包含头文件 #include<iterator>。
(1)反向迭代器
(2)插入迭代器适配器
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
int main()
{
vector<int> vecInt = {1,2,3,4,5};
vector<int>::iterator it=vecInt.begin();
for(auto &elem:vecInt)
cout<<elem<<" ";
cout<<endl<<"-----------------------------------------"<<endl;
ostream_iterator<int> osi (cout," "); //创建输出流迭代器
vector<int>::reverse_iterator rit = vecInt.rbegin(); //创建反向迭代器
copy(rit,vecInt.rend(),osi); //输出,容器中的内容拷贝到输出流迭代器中
//rit直接换成vecInt.rbegin()也可以
cout<<endl;
return 0;
}
|
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
using namespace std;
template <typename Container>
void printElements(Container c)
{
typename Container :: iterator it;
for(it = c.begin();it != c.end(); ++it)
{
cout<<*it<<" ";
}
cout<<endl;
}
int main()
{
vector<int> vecSrc = {1,2,3};
list<int> listDest;
copy(vecSrc.begin(),vecSrc.end(),back_insert_iterator<list<int> >(listDest));
//尾插法,把vecSrc中的内容插入到listDest
printElements(listDest);
cout<<"--------------------------------"<<endl;
list<int> listDest1;
copy(vecSrc.begin(),vecSrc.end(),front_insert_iterator<list<int> >(listDest1));
//头插法,把vecSrc中的内容插入到listDest1
printElements(listDest1);
cout<<"--------------------------------"<<endl;
copy(vecSrc.begin(),vecSrc.end(),insert_iterator<list<int> >(listDest,++listDest.begin()));
//指定位置插入法,把vecSrc中的内容,从listDest2的第二个位置开始插入
printElements(listDest);
return 0;
}
|
函数适配器:
函数适配器共有如下3种:
#include <functional>
1. 绑定器,有两个:
bind1st (函数对象,指定值); (过时)
将指定值绑定到函数对象的第1个参数上。
bind2nd (函数对象,指定值); (过时)
将指定值绑定到函数对象的第2个参数上。
bind (函数对象,指定值… C++11)
绑定的参数的个数不受限制;对于不事先绑定的参数,需要传std::placeholders进去,从 _1 开始,依次递增(占位符)
2. 否定器,也有两个:
——not1() //用于逆转一元断言
——not2() //用于逆转二元断言
3. 成员函数适配器,也是两个:
——mem_fun() //容器参数为类指针
——mem_fun_ref() //容器参数为类对象
——mem_fn() 两者都能用(C++11)
绑定的参数的个数不受限制;对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增
|
#include <iostream>
#include <functional>
using namespace std;
int func(int x,int y)
{
return x+y;
}
class A
{
public:
A()
{
cout<<"A()"<<endl;
}
A(const A & rhs)
{
cout<<"A(const A&)"<<endl;
}
int func(int x,int y)
{
cout<<"A::func(int,int)"<<endl;
cout<<"x="<<x<<endl;
cout<<"y="<<y<<endl;
return x+y;
}
};
int main()
{
auto f1=bind(func,10,placeholders::_1);
//绑定函数func,第一个参数为10,另外一个参数先不绑定,使用占位符
cout<<f1(20)<<endl; //占位符所在参数为20
A a;
auto f2=bind(&A::func,&a,placeholders::_1,placeholders::_2);
//这里A::func必须取地址,不然报错:这不是一个静态成员
//&a 和 a 的区别,一个不调拷贝构造函数,一个调构造函数
// auto f2=bind(&A::func,placeholders::_1,placeholders::_2,placeholders::_3);
// cout<<f2(a,1,2)<<endl;
cout<<f2(1,2)<<endl;
return 0;
}
|
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
void f(int n1,int n2,int n3,const int & n4,int & n5)
{
cout<<"("<<n1<<","<<n2<<","<<n3<<","<<n4<<","<<n5<<")"<<endl;
}
struct Foo
{
int data=10; //C++11新特性
};
int main()
{
int n=7,m=8;
auto f1=bind(f,_2,_1,42,cref(n),ref(m)); //占位符数字表示第几个参数
n=10;
f1(1,2,1001,1002,1003);
//2,1,42,10,8 实参调用时可以传递多余的参数,但是无效
Foo foo;
foo.data = 12;
auto f3 = bind(&Foo::data,_1); //还可以绑定数据成员
cout<<f3(foo)<<endl;
// auto f4 = bind(&Foo::data,foo);
// cout<<f4(foo)<<endl;
return 0;
}
|
#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders;
struct foo
{
void sum(int x,int y) { cout<<x+y<<endl; }
int data = 10;
};
int main()
{
foo fo;
auto f1 = bind(&foo::sum,fo,_1,_2);
f1(1,2);
fo.data = 12;
auto f2 = bind(&foo::data,&fo); // &fo,不要写fo,这样效率不高
cout<<f2(10)<<endl; // 12
auto f3 = bind(&foo::data,_1); // 编译通过,但是不知道怎么用 f3(fo);
}
//3
//12
|
//函数适配器
//否定器,not1() 用于逆转一元断言
//not2() 用于逆转二元断言
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
template<typename Container>
void print(Container& v)
{
for(auto& elem:v)
cout<<elem<<" ";
cout<<endl;
}
int main()
{
int arr[] = {1,2,3,4,5,6,7};
vector<int> v1(arr,arr+sizeof(arr)/sizeof(int));
print(v1);
less<vector<int>::value_type> it;
vector<int> tmp(v1);
replace_if(tmp.begin(),tmp.end(),bind1st(it,3),7); // it为小于3,最终就是大于3的数据改成7
print(tmp);
tmp.clear();
tmp = v1;
replace_if(tmp.begin(),tmp.end(),not1(bind1st(it,3)),7); // 否定器,小于3的改成7
print(tmp);
tmp.clear();
tmp = v1;
replace_if(tmp.begin(),tmp.end(),bind1st(not2(it),3),7); // it被否定成大于3,所以最终就是小于3的数据被换成7
print(tmp);
}
|
//成员函数适配器
#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders;
struct foo
{
void display_greeting(){ cout<<"hello,world!"<<endl; }
void display_num(int n){ cout<<n<<endl; }
int data = 7;
};
int main()
{
foo fo;
auto f1 = mem_fn(&foo::display_greeting); // _1这个占位符可要可不要
f1(fo);
auto f2 = mem_fn(&foo::display_num);
f2(fo,6);
auto f3 = mem_fn(&foo::data);
cout<<f3(fo)<<endl;
return 0;
}
|
//成员函数适配器
//mem_fun() //函数参数为类指针
#include<iostream>
#include<functional>
#include<algorithm>
#include<vector>
using namespace std;
class Num
{
int _val;
public:
Num(){ _val=0; }
Num(int val){ _val=val; }
bool display(){ cout<<_val<<" "; return true; }
int squareval(){ _val*=_val; return _val; }
int lessconst(int k){ _val-=k;return _val; }
friend ostream& operator<<(ostream& os,const Num& rhs);
};
ostream& operator<<(ostream& os,const Num& rhs)
{
os<<rhs._val;
}
int main()
{
vector<Num*> v1;
Num arr[10];
for(int i=0;i<10;++i)
{
arr[i] = Num(i+1);
v1.push_back(&arr[i]);
}
cout<<"原始数据:"<<endl;
for_each(v1.begin(),v1.end(),mem_fun(&Num::display));
//for_each(v1.begin(),v1.end(),mem_fun<bool,Num>(&Num::display));
// 两种写法都可以啊
cout<<endl;
// for_each(v1.begin(),v1.end(),mem_fun(&Num::squareval));
for_each(v1.begin(),v1.end(),mem_fun<int,Num>(&Num::squareval));
cout<<"数据平方:"<<endl;
for(auto& elem:v1)
cout<<*elem<<" ";
cout<<endl;
for_each(v1.begin(),v1.end(),bind2nd(mem_fun<int,Num>(&Num::lessconst),5));
// bind2nd(函数对象,指定值) 把指定值绑定到函数对象的第二个参数上
cout<<"减去常数:"<<endl;
for(auto& elem:v1)
cout<<*elem<<" ";
cout<<endl;
return 0;
}
|
//成员函数适配器
//mem_fun_ref() // 函数参数为类对象
#include<iostream>
#include<functional>
#include<algorithm>
#include<vector>
using namespace std;
class Num
{
public:
Num(){ val = 0; }
Num(int _val){ val = _val; }
bool display(){ cout<<val<<" "; return true; }
bool isEven(){ return (bool)(val%2); }
bool isPrime()
{
for(int i=2;i<(val/2);++i)
if(!(val%i)) return false;
return true;
}
friend ostream& operator<<(ostream& os,const Num& rhs);
private:
int val;
};
ostream& operator<<(ostream& os,const Num& rhs)
{
os<<rhs.val;
}
|
int main()
{
vector<Num> v1(12); // 开辟12个空间
//容器参数为类对象,Num
for(int i=0;i<12;++i)
{
v1[i] = Num(i+1);
}
vector<Num>::iterator it;
cout<<"原始数据:"<<endl;
// for_each(v1.begin(),v1.end(),mem_fun_ref(&Num::display));
for_each(v1.begin(),v1.end(),mem_fun_ref<bool,Num>(&Num::display)); // 这样写也可以
cout<<endl;
cout<<"删除质数:"<<endl;
it = remove_if(v1.begin(),v1.end(),mem_fun_ref(&Num::isPrime));
for(auto& elem:v1)
cout<<elem<<" ";
cout<<endl;
v1.erase(it,v1.end());
for(auto& elem:v1)
cout<<elem<<" ";
cout<<endl;
vector<Num> v2(12);
for(int i=0;i<12;++i)
{
v2[i] = Num(i+1);
}
v2.erase(remove_if(v2.begin(),v2.end(),mem_fun_ref(&Num::isEven)),v2.end());
cout<<"删除基数:"<<endl;
for(auto& elem:v2)
cout<<elem<<" ";
cout<<endl;
return 0;
}
|