1、代码

1.1 调试信息的配置

//一个调试开关,如果要看调试信息,就把这个开关的注释去掉
//#define USEDEBUG//如果调试开关打开了,就定义好调试的输出函数(其实是个宏),
#ifdef USEDEBUG
#define DEBUG(fmt, arg...)\do{\printf("%s %d %s() : ", __FILE__, __LINE__, __func__);\printf(fmt, ##arg);\}while(0)
#else
//如果没有打开,这个函数什么也不做
#define DEBUG(fmt, arg...)
#endif

1.2 栈类的声明

//定义模版类 ClsStack
template<typename T> class ClsStack
{//这个类的=型私有数据,主要用于对栈的内存分配进行管理,//用户不需要关心内存,只需要调用对外提供的几个方法就可以了private :T ** __m_Data;//存储数据的内存开始地址int  __m_pos;//记录栈尾的位置,插入数据时插入这个位置int  __m_memsize;//记录内存的总数protected ://重新分配内存空间,可以减小,也可以增大int __resize(int n);//获取给定参数的双倍内存,其实主要目的是防止参数是0int __doublesize(int n);public :ClsStack(int n = 0);~ClsStack();//弹出栈顶int  pop (T ** ppData);//获取栈顶元素,但是不弹出int  top (T ** ppData);//向栈添加数据int  push(T * pData);//清空整个栈的数据int clear(void (*)(T*));//输出整个栈的数据,用于调试void printStack(T * p[], int pos);
};

1.3 构造函数的实现

//构造函数
//默认参数值是0
//参数非零时的作用是用于初始化栈空间的大小
template<typename T> ClsStack<T>::ClsStack(int n)
{__m_Data = NULL;__m_pos = -1;__m_memsize = 0;if(0 != n){__m_Data = new T * [n];if(NULL != __m_Data){__m_memsize = n;}}
}

1.4) 析构函数的实现

//析构函数
//在栈对象被销毁时,需要把申请的内存空间释放
template<typename T> ClsStack<T>::~ClsStack()
{if(NULL != __m_Data){delete __m_Data;__m_Data = NULL;}__m_pos = -1;__m_memsize = 0;
}

1.5)内存控制函数

//计算新的内存空间
//当参数是0的时候,指定内存空间是1
//参数不是0的时候,内存加倍
template<typename T> int ClsStack<T>::__doublesize(int n)
{int x = 0;if(0 == n){x = 1;}else{x = n * 2;}return x;
}//重新设定栈的大小
//就是扩展当前的内存容量到指定的大小
template<typename T> int ClsStack<T>::__resize(int n)
{T ** p = new T * [n];if(NULL == p){return -1;}memset(p, 0, sizeof(T *) * (n));if(NULL != __m_Data){//printStack(__m_Data, __m_pos);if( NULL == memcpy(p, __m_Data, __m_memsize * sizeof(T *))){DEBUG("memcpy faild\n");delete p;return -1;}//printStack(p, __m_pos);delete __m_Data;}__m_Data = p;__m_memsize = n;return 0;
}

1.6)栈操作函数的实现

//弹出数据
//数据通过参数指定的指针返回
template<typename T> int ClsStack<T>::pop(T ** ppData)
{if(NULL == ppData){return -1;}int r = 0;if(-1 == __m_pos){*ppData = NULL;r = -1;}else{*ppData = __m_Data[__m_pos --];r = 0;DEBUG("memsize : [%u], pos : [%d], p = [0X%08X]\n", __m_memsize, __m_pos + 1, (unsigned int)*ppData);}return r;
}//获取栈顶元素,并不弹出
template<typename T> int ClsStack<T>::top(T ** ppData)
{if(NULL == ppData){return -1;}int r = 0;if(-1 == __m_pos){*ppData = NULL;r = -1;}else{*ppData = __m_Data[__m_pos];r = 0;}return r;
}//向栈压入元素
//栈会自己判断内存,如果内存不足会自动增加内存
template<typename T> int ClsStack<T>::push(T * pData)
{if(__m_pos + 1 >= __m_memsize){int n = __doublesize(__m_memsize);if(0 != __resize(n)){return -1;}}__m_Data[++__m_pos] = pData;DEBUG("memsize : [%u], pos : [%d], p = [0X%08X]\n", __m_memsize, __m_pos, (unsigned int)__m_Data[__m_pos]);return 0;
}

1.7)清空栈数据函数

//清空栈,需要指定回收元素数据的函数,
//否则无法知道如何回收由用户申请的内存空间
template<typename T> int ClsStack<T>::clear(void (*F)(T *))
{if(NULL == F && __m_pos >= 0){return -1;}if(NULL != __m_Data && 0 != __m_memsize){for(int i = 0; i <= __m_pos; i++){F(__m_Data[i]);__m_Data[i] = NULL;}delete __m_Data;}__m_Data = NULL;__m_pos = -1;__m_memsize = 0;
}

1.8)调试辅助函数

//输出栈的内存状态,调试时使用
template<typename T> void ClsStack<T>::printStack(T * p[], int pos)
{int i = 0;for(i = 0; i <= pos; i++){printf("[%08u] = [0X%08X]\n", i, NULL == p ? 0 : p[i]);}printf("----------------------------\n");
}

1.9)测试代码

//test 函数定义
#define TEST_EQ(a, b)\do{\if(a == b)\{\printf("\033[0;32m[SUCCESS %5d]\033[0m\n", __LINE__);\}\else\{\printf("\033[0;31m[FAILD   %5d]\033[0m\n", __LINE__);\}\}while(0)int main()
{ClsStack<int> objStack;int x = 10;int * p = &x;//向栈内压入数据
    objStack.push(p);int i = 0;for(i = 0; i <= 10; i++){int * z = new int;*z = i;objStack.push(z);}//开始弹出数据for(i = 10; i >= 0; i--){int * z = NULL;objStack.pop(&z);if(NULL == z){printf("z == NULL\n");continue;}//测试弹出的数据和压入的数据是否一致TEST_EQ(i, *z);delete z;}int * g = NULL;objStack.pop(&g);TEST_EQ(x, *g);
}

完整代码如下(折叠了) :

 View Code

2、运行结果

  2.1、编译

g++ -g  -c -o stack.o stack.cpp -Wall -I./
g++ -g  -o stack stack.o -Wall -I./ 

  2.2、运行结果

$ ./stack
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   288]
[SUCCESS   293]

本文转自郝峰波博客园博客,原文链接:http://www.cnblogs.com/fengbohello/p/4547598.html,如需转载请自行联系原作者

C++实现一个栈(使用类模板)相关推荐

  1. C++学习笔记:类模板

    上一章我们介绍了函数模板,今天这章我们来学习类模板. 类模板声明 template是声明类模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个,可以是**「类型参数」** ,也可以是**非 ...

  2. C++ Primer 5th笔记(chap 16 模板和泛型编程)类模板和static

    1. 定义 与任何其他static数据成员相同,模板类的每个static数据成员必须有且仅有一个定义.类模板的每个实例都有一个独有的static对象. eg. Foo是一个类模板 有一个名为count ...

  3. 函数模板和类模板的使用

    函数模板 //交换 int 变量的值 void Swap(int *a, int *b){ int temp = *a; *a = *b; *b = temp; } //交换 float 变量的值 v ...

  4. C++类模板 template class T详细使用方法

    C++类模板 template <class T>详细使用方法 类模板与函数模板的定义和使用类似. 有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,如下面语句声明了一个类: cl ...

  5. 1分钟理清楚C++类模板和模板类区别

    目录 1.定义区别 2.程序举例 1.定义区别 类模板和模板类主要关注点是后一个单词. 类模板:主要描述的是模板,这个模板是类的模板.可以理解为一个通用的类,这个类中的数据成员,成员函数的形参类型以及 ...

  6. 友元函数,友元类,类模板

    C++提供友元机制,允许外部类和函数访问类的私有成员和保护成员的辅助方法,即将它们声明为一个给定类的友元类(或友元函数),使其具有类成员函数的访问权限.但友元本身不是类的成员,它不属于任何类. 优点: ...

  7. C++:类模板与模板类的区别

    写在前面:(模板类是类模板实例化后的一个产物,类模板比作是一个作饺子的模子,而模板类就是用这个模子做出来的饺子,至于饺子什么馅儿的就需要你自己去实例化自己的内容.) 类模板:说明该类是一个模板,它代表 ...

  8. C++学习笔记——类模板

    类模板 类模板的定义和声明 1. 定义 template <typename T> class B {}; 2. 声明 template <typename T> class ...

  9. 函数模板和类模板 模版特化

    函数模板和类模板 模版特化 关键字: template <class t>, template <typename t> 模板 模板(template)是一个将数据类型参化的工 ...

  10. 类模板实现基于数组的栈

    一.学习要点: 1.类模板和模板类的区别,模板类这里的模板可以看成一个动词,对抽象类的一个实例化: 2.函数模板的声明和定义: 3.基于数组栈的实现,进栈和出栈的差别,进栈[++top],出栈[top ...

最新文章

  1. cacti由cmd.php更换成spine后无法绘图
  2. 安装最新版git,git升级
  3. Elasticsearch 摄取节点(Ingest Node)常用的数据处理器(Processor)
  4. box-sizing的使用
  5. tomcat安装成功页面翻译
  6. tasker运行java_Tasker 打开桌面快捷方式(以微信公众号为例)[No Root]
  7. 强化学习的数学基础2---PPO算法
  8. websocket实时聊天(一)
  9. caffe 安装(only cpu)
  10. CC***原理及防范方法
  11. 10页PPT,看懂 SaaS 客户生命周期
  12. wps怎么将字体变得很大_wps如何将字体无限放大
  13. 计算机显示去掉拼音分类,win10系统取消电脑文件显示以字母数字拼音分组的解决方法...
  14. 80和443端口的区别
  15. 利用PS如何进行精细抠图
  16. C语言—内存的管理和释放
  17. 服务器端方法级权限控制----------@Secured注解的使用
  18. 【彩艳】ArcGIS影像裁剪说明
  19. ArcGIS教程:区域填充
  20. 俄语计算机考研,研友分享:俄语考研91分的经验体会

热门文章

  1. Shell——常用工具(cut、sed、awk、sort)
  2. 知己知彼 防范攻击:网络攻击步骤与黑客攻击原理
  3. leecode_二叉树中序遍历
  4. 02-HTTP的请求方法以及响应状态码
  5. Postfix 邮件服务 - 基础服务
  6. 【小游戏】有意思的小游戏集合
  7. python,面向对象的各种方法
  8. WIN7+wampserver2.4+zend stadio10.6.1配置Xdebug
  9. Jbox帮助文档,默认的属性含义
  10. WCF HelpPage 和自动根据头返回JSON XML