设为首页 加入收藏

TOP

2.2.1 栈类模板实例
2013-10-07 16:30:48 来源: 作者: 【 】 浏览:257
Tags:2.2.1 模板 实例

2.2 实践——栈类模板

例2.1中只是定义一个复合数据结构,并没有涉及成员函数等。而类模板与普通类一样,可以有各种成员函数、继承、运算符重载等。为了使例子更加丰满一些,我们来设计一个虽然简陋但功能完整的栈类模板。

2.2.1 栈类模板实例

首先,要有一个栈类来封装数据入栈/出栈的操作,并且可以报告栈是否为空。为使其可用于多种数据类型,该栈类显然也应该写成一个类模板。这里将该栈类模板命名为my_stack。

其次,例2.1的栈节点类模板list_node应当只为栈类模板所用。为简化代码,可以将list_node所有成员完全私有,但声明my_stack为友元类,使其可以访问list_node的私有成员。my_stack负责组织由list_node组成的单向链表。这样一个栈类模板代码如例2.2所示。

例2.2

  1.  
  2. // -----------------------------  
  3. // 文件名:stack.hpp  
  4. #include <stdexcept> 
  5.  
  6. template<typename T> class my_stack; // 前置栈类模板声明  
  7.  
  8. template<typename T> 
  9. class list_node  
  10. {  
  11.     T value;  
  12.     list_node *next;  
  13.  
  14.     // 私有构造函数,只能由其友类构造  
  15.     list_node(T const &v, list_node *n) :  
  16.         value(v), next(n) {}  
  17.  
  18.     // 友类必须是类模板my_stack的实例  
  19.     friend class my_stack<T>;  
  20. };  
  21.  
  22. template<typename T=int> 
  23. class my_stack  
  24. {  
  25.     typedef list_node<T> node_type;  
  26.     node_type *head;  
  27.  
  28.     // my_stack不可复制构造,也不可赋值  
  29.     my_stack operator=(my_stack const &) {}  
  30.     my_stack(my_stack const &s) {}  
  31.  
  32. public:  
  33.     // 构造与析构  
  34.     my_stack() : head(0) {}  
  35.     ~my_stack() {while (!empty()) pop();}  
  36.  
  37.     // 在类模板内实现的成员函数模板  
  38.     bool empty() const {return head == 0;}  
  39.     T const& top() const throw (std::runtime_error) {  
  40.         if (empty())  
  41.             throw std::runtime_error("stack is empty.");  
  42.         return head->value;  
  43.     }  
  44.     void push(T const &v) {head = new node_type(v, head);}  
  45.  
  46.     // 成员函数声明,将在类模板外实现  
  47.     void pop();  
  48. };  
  49.  
  50. // 在类模板外实现的成员函数模板  
  51. template<typename T> 
  52. void my_stack<T>::pop()  
  53. {  
  54.     if (head) {  
  55.         node_type *tmp = head;  
  56.         headhead = head->next;  
  57.         delete tmp;  
  58.     }  

例2.2中首先是类模板my_stack的前置声明。有此前置声明,编译器已知my_stack为类模板且需要一个模板参数,则认可之后遇到的my_stack<T>为合法声明,否则将报错。

类模板list_node内容不变,只是所有成员都是私有,并且声明my_stack<T>为其友类,以便my_stack直接访问其成员。接下来是一个略微复杂的my_stack类模板。在类模板内首先用typedef为list_node<T>赋一个别名node_type。这样在随后用到list_node模板时就无须一一给出实参。在需要用到大量模板实例类型时,这样做可以使得代码看起来更简洁。在以后的例子中还会看到,typedef在模板编程(www.cppentry.com)中的作用远不止于使代码整洁这么简单。

my_stack中只有一个成员变量,即由node_type组成的单向链表的表头指针。鉴于该指针是独占指针,即其所指内容不可与其他指针共享,为防止对栈进行复制构造或者赋值操作时破坏其独占权,最简单的处理方式是将复制构造函数及赋值操作符声明为私有,以禁止用户调用。

随后即为my_stack类模板的公开构造、析构函数和若干成员函数。函数本身并无新意,重点在于模板中成员函数的写法。既然my_stack是一个类模板,其成员函数也天然是模板,并且继承了类模板的参数。在C++(www.cppentry.com)中,类成员函数的实现代码既可以直接写在类实现体内,也可以单独写在类实现体外。对于第一种方式,类模板的成员函数与普通类的成员函数的写法并无多少差异,如例2.2中my_stack的成员函数top()。而对于第二种方式,由于类模板成员函数本身也是模板,单独实现时也需要写成模板。已知普通类成员函数在外部实现时,代码如下:

  1. return_value class_name::func_name(param_list) {/*函数实现体*/} 

对于类模板成员函数来说,class_name本身是一个模板名,则需要写成如下所示:

  1. template<T> 
  2. return_value class_name<T>::func_name(param_list) {/*函数实现*/} 

例2.2中my_stack的成员函数pop()即是如此。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇2.1 类型无关的数据结构 下一篇2.2.2 栈类模板衍生子类模板实例

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: