本文实现了STL中stack的大部分功能,同时添加了一些功能。

注意以下几点:

1.Stack是一种适配器,底层以vector、list、deque等实现

2.Stack不含有迭代器

在本例中,我添加了几项功能,包括不同类型stack之间的复制和赋值功能,可以实现诸如Stack<int, vector<int> >和Stack<double, list<double> >之间的复制和赋值,这主要依靠成员函数模板来实现。

为了更方便的实现以上功能,我添加了一个函数:

  1. const_container_reference get_container() const

来获取内部容器的引用。

此外,标准库的stack不检查越界行为,我为stack添加了异常处理,当栈空时,执行pop或者top会抛出异常。这个异常类继承自Exception(见上篇文章),用来标示栈空。

详细代码如下:Exception的实现见:借助backtrace和demangle实现异常类Exception

  1. #ifndef STACK_HPP_
  2. #define STACK_HPP_
  3.  
  4. #include "Exception.h"
  5. #include <deque>
  6.  
  7. //栈空引发的异常
  8. class EmptyStackException : public Exception
  9. {
  10. public:
  11. EmptyStackException() :Exception("read empty stack") { }
  12. };
  13.  
  14. template <typename T, typename Container = std::deque<T> >
  15. class Stack
  16. {
  17. public:
  18. typedef T value_type;
  19. typedef T& reference;
  20. typedef const T& const_reference;
  21. typedef Container container_type; //容器类型
  22. typedef EmptyStackException exception_type; //异常类型
  23. typedef typename Container::size_type size_type;
  24. typedef Container &container_reference; //容器引用
  25. typedef const Container& const_container_reference;
  26.  
  27. explicit Stack(const container_type &cont = container_type()) :cont_(cont) { }
  1. //不同类型间实现复制
  2. template <typename T2, typename Container2>
  3. Stack<T, Container>(const Stack<T2, Container2> &s);
  4.  
  5. //不同类型间进行赋值
  6. template <typename T2, typename Container2>
  7. Stack<T, Container> &operator=(const Stack<T2, Container2> &s);
  8.  
  9. void push(const value_type &val) { cont_.push_back(val); }
  10. void pop()
  11. {
  12. if(cont_.empty())
  13. throw exception_type();
  14. cont_.pop_back();
  15. }
  16.  
  17. reference top()
  18. {
  19. if(cont_.empty())
  20. throw exception_type();
  21. return cont_.back();
  22. }
  23. const_reference top() const
  24. {
  25. if(cont_.empty())
  26. throw exception_type();
  27. return cont_.back();
  28. }
  29.  
  30. bool empty() const { return cont_.empty(); }
  31. size_type size() const { return cont_.size(); }
  32.  
  33. //获取内部容器的引用
  34. const_container_reference get_container() const
  35. { return cont_; }
  36.  
  37. friend bool operator==(const Stack &a, const Stack &b)
  38. {
  39. return a.cont_ == b.cont_;
  40. }
  41. friend bool operator!=(const Stack &a, const Stack &b)
  42. {
  43. return a.cont_ != b.cont_;
  44. }
  45. friend bool operator<(const Stack &a, const Stack &b)
  46. {
  47. return a.cont_ < b.cont_;
  48. }
  49. friend bool operator>(const Stack &a, const Stack &b)
  50. {
  51. return a.cont_ > b.cont_;
  52. }
  53. friend bool operator<=(const Stack &a, const Stack &b)
  54. {
  55. return a.cont_ <= b.cont_;
  56. }
  57. friend bool operator>=(const Stack &a, const Stack &b)
  58. {
  59. return a.cont_ >= b.cont_;
  60. }
  61.  
  62. private:
  63. Container cont_;
  64. };
  65.  
  66. template <typename T, typename Container>
  67. template <typename T2, typename Container2>
  68. Stack<T, Container>::Stack(const Stack<T2, Container2> &s)
  69. :cont_(s.get_container().begin(), s.get_container().end())
  70. {
  71.  
  72. }
  73.  
  74. template <typename T, typename Container>
  75. template <typename T2, typename Container2>
  76. Stack<T, Container> &Stack<T, Container>::operator=(const Stack<T2, Container2> &s)
  77. {
  78. if((void*)this != (void*)&s)
  79. {
  80. cont_.assign(s.get_container().begin(), s.get_container().end());
  81. }
  82.  
  83. return *this;
  84. }
  85.  
  86. #endif /* STACK_HPP_ */

测试代码如下:

  1. #include "Stack.hpp"
  2. #include <iostream>
  3. #include <string>
  4. #include <vector>
  5. #include <list>
  6. #include <stdio.h>
  7. using namespace std;
  8.  
  9. int main(int argc, char const *argv[])
  10. {
  11.  
  12. try
  13. {
  14. Stack<string, vector<string> > st;
  15. st.push("foo");
  16. st.push("bar");
  17.  
  18. Stack<string, list<string> > st2(st);
  19. //st2 = st;
  20.  
  21. while(!st2.empty())
  22. {
  23. cout << st2.top() << endl;
  24. st2.pop();
  25. }
  26.  
  27. st2.pop(); //引发异常
  28. }
  29. catch (const Exception& ex)
  30. {
  31. fprintf(stderr, "reason: %s\n", ex.what());
  32. fprintf(stderr, "stack trace: %s\n", ex.stackTrace());
  33. }
  34.  
  35. return 0;
  36. }

标准库Stack的一种实现的更多相关文章

  1. C++ 异常机制分析(C++标准库定义了12种异常,很多大公司的C++编码规范也是明确禁止使用异常的,如google、Qt)

    阅读目录 C++异常机制概述 throw 关键字 异常对象 catch 关键字 栈展开.RAII 异常机制与构造函数 异常机制与析构函数 noexcept修饰符与noexcept操作符 异常处理的性能 ...

  2. 标准库priority_queue的一种实现

    优先级队列相对于普通队列,提供了插队功能,每次最先出队的不是最先入队的元素,而是优先级最高的元素. 它的实现采用了标准库提供的heap算法.该系列算法一共提供了四个函数.使用方式如下: 首先,建立一个 ...

  3. C++标准库(体系结构与内核分析)(侯捷第二讲)

    一.OOP和GP的区别(video7) OOP:面向对象编程(Object-Oriented programming) GP:泛化编程(Generic programming) 对于OOP来说,我们要 ...

  4. C++ 标准库类型-String,Vector and Bitset

    <C++ Primer 4th>读书摘要 最重要的标准库类型是 string 和 vector,它们分别定义了大小可变的字符串和集合.这些标准库类型是语言组成部分中更基本的那些数据类型(如 ...

  5. 关于标准库中的ptr_fun/binary_function/bind1st/bind2nd

    http://www.cnblogs.com/shootingstars/archive/2008/11/14/860042.html 以前使用bind1st以及bind2nd很少,后来发现这两个函数 ...

  6. Python内置模块与标准库

    Python内置模块就是标准库(模块)吗?或者说Python的自带string模块是内置模块吗? 答案是:string不是内置模块,它是标准库.也就是说Python内置模块和标准库并不是同一种东西. ...

  7. Python标准库:1. 介绍

    标准库包括了几种不同类型的库. 首先是那些核心语言的数据类型库,比方数字和列表相关的库.在核心语言手冊里仅仅是描写叙述数字和列表的编写方式,以及它的排列,而未定义它的语义. 换一句话说,核心语言手冊仅 ...

  8. C++标准库类模板(stack)和 队列(queue)

    在C++标准库(STL)中有栈和队列的类模板,因此可以直接使用 1.栈(stack):使用栈之前,要先包含头文件 : #include<stack> stack.push(elem); / ...

  9. 谈谈两种标准库类型---string和vector

    两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库 ...

随机推荐

  1. linux之expr命令

    expr命令可以实现数值运算.数值或字符串比较.字符串匹配.字符串提取.字符串长度计算等功能.它还具有几个特殊功能,判断变量或参数是否为整数.是否为空.是否为0等. 先看expr命令的info文档in ...

  2. 今天写页面,将.net也使用了语义法规来判断。做法来源是.net ado.net的类型判断 Infertype。一样的原理

    做了一个封装,使页面更容易维护一些.主要是两个方法,如下所示: private void BindModule(Action<Repeater, string> bindSingRpt)  ...

  3. Linux内核中的中断栈与内核栈的补充说明【转】

    转自:http://blog.chinaunix.net/uid-12461657-id-3487463.html 原文地址:Linux内核中的中断栈与内核栈的补充说明 作者:MagicBoy2010 ...

  4. Request的Body只能读取一次解决方法

    一.需要一个类继承HttpServletRequestWrapper,该类继承了ServletRequestWrapper并实现了HttpServletRequest, 因此它可作为request在F ...

  5. 【原创】Talend ETL开发——基于joblet的统一的email发送

    更新 2019/1/16:增加了允许5个附件发送.smtp等配置的字段. 一.背景 在ETL数据整合过程中,肯定会涉及到email的通知,比如ETL的执行情况汇报,执行耗时汇报,关键数据更新情况等信息 ...

  6. 新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)B 杨老师的游戏【暴力/next-permutation函数/dfs】

    链接:https://www.nowcoder.com/acm/contest/116/B 来源:牛客网 题目描述 杨老师给同学们玩个游戏,要求使用乘法和减法来表示一个数,他给大家9张卡片,然后报出一 ...

  7. SpringCloud集群(三)

    一.构造步骤 1.进行其他的服务中心的域名映射 127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 127.0.0.1 eureka7003.com 2 ...

  8. 用jmeter进行多用户并发压力测试

    测试要求如下,多用户同时登陆web应用程序,并进行操作,查看在多用户操作下,程序的performence.恰好,jemter下有个CSV Data Set Config,它用来设定一组参数,以便在向程 ...

  9. HttpClient 同时上传多个文件及参数, 同时利用 Web Api 接收

    using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient()) { client.BaseAddress = ...

  10. ReactiveCocoa(二)

    前言 通过ReactiveCocoa(一)的学习,相信大家对ReactiveCocoa有了一些基本认识吧.下面就让我们来学习ReactiveCocoa的一些基本使用吧! ReactiveCocoa基本 ...