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

来源:互联网 发布:网络电视剧生死征途 编辑:程序博客网 时间:2024/06/05 05:24

一、需求引入

上一篇博客实作了一个「元素个数可变」的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」 的需求。 更好的作法是让使用者指定这两个参数的值, 并在文件中说明它们的意义

0 0
原创粉丝点击