Nontype Class Template Parameters(非类型类模板参数)

固定大小栈实现
本文介绍了一种使用固定大小数组实现的栈数据结构。通过模板参数指定栈的最大容量,避免了内存管理问题。提供了完整的C++代码示例及如何实例化不同类型的栈。

一、需求引入

上一篇博客实作了一个「元素个数可变」的stack   class。与之对比,你也可以实作另一种stack,透过一个固定大小(fixed-size)的 array来容纳元素。这样做的好处是不必考虑诸如内存管理之类的问题。然而array大小的决定是一件比较困难的事:array愈小则stack愈容易满溢,array愈大则愈容易造成空间浪费 。 一个可行的解决办法是让使用者指定array大小 , 这个大小也就是stack  的最大元素个数。


二、代码示例

 为了完成以上想法,我们应该把大小值当作一个  template parameter: 

#include <stdexcept> 
 
template <typename T, int MAXSIZE> 
class Stack { 
private: 

//  元素 
T elems[MAXSIZE]; 

//  当前的元素个数 
int numElems; 


public: 

 //  构造函数 
Stack();

// push 元素
void push(T const&); 

// pop 元素 
void pop(); 

//  传回  stack 顶端元素  
T top() const; 

// stack 是否为空 
bool empty() const { 
return numElems == 0; 
}  

// stack 是否已满 
bool full() const { 
return numElems == MAXSIZE; 

}; 
 
//  构造函数 

//  一开始并无任何元素 
template <typename T, int MAXSIZE> 
Stack<T,MAXSIZE>::Stack () : numElems(0) { 
//  不做任何事 

 
template <typename T, int MAXSIZE> 
void Stack<T,MAXSIZE>::push (T const& elem) { 
if (numElems == MAXSIZE) { 
throw std::out_of_range("Stack<>::push(): stack is full."); 

//  追加 
elems[numElems] = elem; 

//  元素总数加  1 
++numElems; 

 
template <typename T, int MAXSIZE> 
void Stack<T,MAXSIZE>::pop () { 
if (numElems <= 0) { 
throw std::out_of_range("Stack<>::pop(): empty stack."); 

//  元素总数减  1 
--numElems; 

 
template <typename T, int MAXSIZE> 
T Stack<T,MAXSIZE>::top () const { 
if (numElems <= 0) { 
throw std::out_of_range("Stack<>::top(): empty stack."); 

//  传回最后一个元素 
return elems[numElems - 1]; 


三、使用

使用上述  class template 时,必须同时指定   (1)   元素类型和   (2) stack 元素的最大数量: 
 
#include <iostream> 
#include <string> 
#include <cstdlib> 
#include "stack4.hpp" 
 
int main() { 


try { 

//  最多容纳  20  个  int  元素 
Stack<int,20> int20Stack; 

//  最多容纳  40  个  int  元素 
Stack<int,40> int40Stack; 

//  最多容纳  40  个  string  元素 
Stack<std::string,40>   stringStack; 
 
//  操控「最多容纳  20  个  int  元素」的那个  stack 
int20Stack.push(7); 
std::cout << int20Stack.top() << std::endl; 
int20Stack.pop(); 
 
//  操控「最多容纳  40  个  string  元素」的那个  stack 
stringStack.push("hello");  32 
std::cout << stringStack.top() << std::endl; 
stringStack.pop(); 

stringStack.pop(); 


} catch (std::exception const& ex) { 
std::cerr << "Exception: " << ex.what() << std::endl; 
return EXIT_FAILURE; //  传回一个错误状态码 



 
注意,每一个被实例化(instantiated) 的  class template 都有各自的类型。 (注:常见的误会是:上述三个  stacks  隶属同一类型。这是错误观念。)因此  int20Stack  和  int40Stack  是两个不同类型,不能互相进行隐式或显式转换,两者不能换用(彼此取代),也不能互相赋值。


你可以指定  non-type template parameters 的默认值: 

template <typename T = int, int MAXSIZE = 100> 
class Stack { 
... 
}; 


然而从设计角度来看,这样做并不恰当。Template parameters 的默认值应该符合大多数情况下的  要求, 然而把  int  当做预设元素类型, 或指定  stack  最多有  100  个元素, 并不符合一个 「通用型 stack」 的需求。 更好的作法是让使用者指定这两个参数的值, 并在文件中说明它们的意义

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值