C++容器适配器的概念与示例
作者:SouLinya
一. 什么是适配器与容器适配器?
适配器是一种设计模式(设计模式是一套被反复使用的,多数人知晓的,经过分类编目的,代码设计经验的总结),该种模式将一个类的接口转换成用户需要的另外一个接口。
举个例子:在日常生活中,当手机没电了,我们需要给手机充电,给手机充电的方式很多,可以插到电源上,也可以用充电宝,还可以直接连着电脑充。而我们并不关心用什么给它充电,我们关心的只是能否给手机充上电。适配器充当的角色就是 给手机充电的接口,它会将不同大小的电压转化成适合给手机充电的电压。容器适配器的概念可以结合这个例子理解,它以 某种容器作为底层结构,改变其接口,使它符合该容器的特性。
容器适配器:以某种已有的既定容器作为底层结构,在其基础上进一步地进行封装接口函数。使其可以满足某种特性。
下面将介绍三个用到容器适配器的结构:stack栈,queue队列,priority_queue优先级队列,通过这三个结构,我们可以更好的理解容器适配器的用途。
二. 理解容器适配器
STL的六大组件
我们可以看出虽然stack,queue,priority_queue中也可以存放数据,但在STL中并没有将其划分在容器的行列,而是将其称为容器配接器,这是因为stack,queue,priority_queue只是对其它容器的接口进行了包装,STL中stack和queue默认使用deque,priority_queue默认使用vector作为容器。我们现在来看看它们的底层接口和实现
stack的模拟实现
知道了容器适配器后,stack的模拟实现就简单了,我们只需要调用指定容器deque的各个成员函数即可实现stack的各个函数接口。
底层实现代码如下:stack底层利用deque双端队列进行包装,需要更改成多参数模板,最便利的一点就是,stack的底层函数的实现可以直接调用容器的函数接口,不需要自己再一步步实现。
namespace nn //命名空间域:防止命名冲突 { //多参数模板 template<class T, class Container = std::deque<T>>//可以明显看出stack配接器的底层容器是deque双端队列,后面会介绍 class stack { public: //元素入栈 void push(const T& x) { _con.push_back(x); } //元素出栈 void pop() { _con.pop_back(); } //获取栈顶元素 T& top() { return _con.back(); } const T& top() const//const修饰 { return _con.back(); } //获取栈中有效元素个数 size_t size() const { return _con.size(); } //判断栈是否为空 bool empty() const { return _con.empty(); } //交换两个栈中的数据 void swap(stack<T, Container>& st)//注意stack<T,Container>才是类型,加引用,别名,减少拷贝 { _con.swap(st._con);//调用deque的算法swap } private: //deque<T> _con底层 Container _con;//将一个类的接口转换成用户需要的另一种接口,即利用deque容器转换成stack配接器 }; }
queue的模拟实现
同样的方式,我们也是通过调用所指定容器的各个成员函数来实现queue的。
底层实现代码如下:
namespace nn //防止命名冲突 { template<class T, class Container = std::deque<T>> class queue { public: //队尾入队列 void push(const T& x) { _con.push_back(x); } //队头出队列 void pop() { _con.pop_front(); } //获取队头元素 T& front() { return _con.front(); } const T& front() const { return _con.front(); } //获取队尾元素 T& back() { return _con.back(); } const T& back() const { return _con.back(); } //获取队列中有效元素个数 size_t size() const { return _con.size(); } //判断队列是否为空 bool empty() const { return _con.empty(); } //交换两个队列中的数据 void swap(queue<T, Container>& q) { _con.swap(q._con); } private: Container _con;//deque<T> _con; }; }
思考stack 和 queue 是否存在迭代器?
stack 和 queue 都不具备迭代器, 因为两者都不具备遍历走访功能,所以自然不需要设计迭代器
stack 和 queue可以以哪些容器作为底层容器?
实际上stack使用vector作为底层容器也是可以的,queue使用deque双端队列+list带头双向循环链表作为底层容器也是可以的。
但是deque在设计上相比于list和vector,作为stack,queue的底层结构更优。
底层容器如何传进去?
作为模板参数传入template<class T,class Container = deque<T>>
,用了默认参数(缺省参数)
到此这篇关于C++容器适配器的概念与示例的文章就介绍到这了,更多相关C++容器适配器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!