1、類模板ios
類模板:將類定義中的數據類型參數化
類模板其實是函數模板的推廣,能夠用相同的類模板來組建任意類型的對象集合
編程
(一)、類模板的定義數組
template <類型形參表>
class <類名>
{ //類說明體 };
template <類型形參表>
<返回類型> <類名> <類型名錶>::<成員函數1>(形參表)
{ //成員函數定義體 }
template <類型形參表>
<返回類型> <類名> <類型名錶>::<成員函數2>(形參表)
{ //成員函數定義體 }
…
template <類型形參表>
<返回類型> <類名> <類型名錶>::<成員函數n>(形參表)
{ //成員函數定義體 }
函數
(二)、使用類模板spa
類模板的實例化:用具體的數據類型替換模板的參數以獲得具體的類(模板類)
模板類也能夠實例化爲對象
用下列方式建立類模板的實例:
.net
類名 <類型實參表> 對象名稱;指針
對於函數模板與類模板,模板參數並不侷限於類型(類類型,基本類型,模板類實例),普通值也能夠做爲模板參數對象
2、Stack類的模板實現blog
在前面曾經分別使用C/C++實現了一個鏈棧,棧中只能放進int類型數據,如今使用模板來從新實現Stack,能夠存放多種數據類型,分別使用自定義鏈棧方式以及自定義數組實現。內存
(一)、自定義鏈棧方式:
stack.h:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
/*************************************************************************
> File Name: stack.h > Author: Simba > Mail: dameng34@163.com > Created Time: 2012年11月03日 星期六 19時28分25秒 ************************************************************************/ #include<iostream> using namespace std; template < class T > class Node { //< >裏面是模板參數,能夠有多個,雖然T用class 聲明,但能夠是內建類型也能夠是class類型 //模板的定義通常寫在頭文件裏 public: Node(T invalue): m_Value(invalue), m_Next(NULL) {} ~Node(); T getValue() const { return m_Value; } void setValue(T value) { m_Value = value; } Node < T > *getNext() const { return m_Next; } void setNext(Node < T > *next) { m_Next = next; } private: T m_Value; Node < T > *m_Next; }; template < class T > Node < T >::~Node() { if (m_Next) { delete m_Next; //自動內存管理,接着找到m_Next指向的下一個結點,一直找到最後的一個結點 //故先釋放最後一個結點(固然是最早壓棧的結點),而後依次返回釋放每個途中的結點 }
" deleted " << endl; } template < class T > class Stack { public: Stack(): m_Head(NULL), m_Count(0) {} ~Stack() { delete m_Head; //自動內存管理 } void push(const T &t); T pop(); T top() const; int count() const; private: Node < T > *m_Head; int m_Count; }; template < class T > void Stack < T >::push(const T &value) { Node < T > *newNode = new Node < T > (value); newNode->setNext(m_Head); m_Head = newNode; ++m_Count; } template < class T > T Stack < T >::pop() { Node < T > *popped = m_Head; if (m_Head != NULL) { m_Head = m_Head->getNext(); T retval = popped->getValue(); popped->setNext(NULL); delete popped; --m_Count; return retval; } return 0; } template < class T > inline T Stack < T >::top() const //模板前綴template < class T > || 函數限定符inline 函數返回值T || //命名空間前綴 Stack < T > //一個類型 || 函數名(函數參數)const 限定符 { return m_Head->getValue(); } template < class T > inline int Stack < T >::count() const { return m_Count; } |
main.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include "stack.h" int main(void) { Stack < int >intstack1, intstack2; int val; for (val = 0; val < 4; ++val) { intstack1.push(val); intstack2.push(2 * val); } while (intstack1.count()) { val = intstack1.pop(); cout << val << endl; } Stack < char >stringstack; stringstack.push('A'); stringstack.push('B'); stringstack.push('C'); char val2; while (stringstack.count()) { val2 = stringstack.pop(); cout << val2 << endl; } cout << "Now intstack2 will be destructed." << endl; return 0; } |
能夠看到雖然intstack2 沒有pop 出元素,但程序結束時,局部對象會被析構,調用析構函數,在析構函數內delete 頭指針,順藤摸瓜一直找到最後一個節點,即首先壓棧的節點,依次返回釋放掉。
(二)、自定義數組方式
Stack2.h:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
#ifndef _STACK2_H_ #define _STACK2_H_ #include <exception> template <typename T, int MAX_SIZE> class Stack2 { public: Stack2(); ~Stack2(); void Push(const T &elem); void Pop(); T &Top(); const T &Top() const; bool Empty() const; private: T *elems_; int top_; }; template <typename T, int MAX_SIZE> Stack2<T, MAX_SIZE>::Stack2() : top_(-1) { elems_ = new T[MAX_SIZE]; } template <typename T, int MAX_SIZE> Stack2<T, MAX_SIZE>::~Stack2() { delete[] elems_; } template <typename T, int MAX_SIZE> void Stack2<T, MAX_SIZE>::Push(const T &elem) { if (top_ + 1 >= MAX_SIZE) throw out_of_range("Stack2<>::Push() Stack2 full"); elems_[++top_] = elem; } template <typename T, int MAX_SIZE> void Stack2<T, MAX_SIZE>::Pop() { if (top_ + 1 == 0) throw out_of_range("Stack2<>::Push() Stack2 empty"); --top_; } template <typename T, int MAX_SIZE> T &Stack2<T, MAX_SIZE>::Top() { if (top_ + 1 == 0) throw out_of_range("Stack2<>::Push() Stack2 empty"); return elems_[top_]; } template <typename T, int MAX_SIZE> const T &Stack2<T, MAX_SIZE>::Top() const { if (top_ + 1 == 0) throw out_of_range("Stack2<>::Push() Stack2 empty"); return elems_[top_]; } template <typename T, int MAX_SIZE> bool Stack2<T, MAX_SIZE>::Empty() const { return top_ + 1 == 0; } #endif // _STACK2_H_ |
main.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include "Stack2.h" #include <iostream> #include<string> using namespace std; int main(void) { Stack2<int, 5> s; s.Push(1); s.Push(2); s.Push(3); while (!s.Empty()) { cout << s.Top() << endl; s.Pop(); } return 0; } |
輸出爲 3 2 1
注意,用數組實現時pop 操做並無刪除元素的操做,只是移動了top 指針,下次push 的時候直接覆蓋便可。再者由於實現了Top 返回棧頂元素,故pop 沒有返回值。
參考:
C++ primer 第四版 Effective C++ 3rd C++編程規範