类模板:将类定义中的数据类型参数化。类模板实际上是函数模板的推广,可以用相同的类模板来组建任意类型的对象集合。
使用类模板,类模板的实例化:用具体的数据类型替换模板参数以得到具体的类。模板类也可以实例化为对象,用下列方式创建类模板的实例:
类名 <类型实参表> 对象名称
函数模板可以自动推导,类模板只能显示实例化。
下面以一个stack模板类来介绍模板的基本用法:
1 #pragma once 2 #include<exception> 3 template <typename T> 4 class Stack 5 { 6 public: 7 Stack(int maxSize); 8 ~Stack(); 9 void push(const T& elem); 10 void pop(); 11 T& top(); 12 const T& top() const; 13 bool empty() const; 14 private: 15 T* elem_; 16 int maxSize_;//栈最大元素个数 17 int top_;//保存栈顶位置 18 }; 19 template<typename T> 20 Stack<T>::Stack(int maxSize) :maxSize_(maxSize),top_(-1) 21 { 22 elem_ = new T[maxSize_]; 23 } 24 template<typename T> 25 Stack<T>::~Stack() 26 { 27 delete[] elem_; 28 } 29 template<typename T> 30 void Stack<T>::push(const T& elem) 31 { 32 if (top_ + 1 >= maxSize_) 33 throw out_of_range("stack<>::push satck full"); 34 elem_[++top_] = elem; 35 } 36 template<typename T> 37 void Stack<T>::pop() 38 { 39 if (top_ + 1 <= 0) 40 throw out_of_range("stack<>::pop stack empty"); 41 --top_; 42 } 43 template<typename T> 44 T& Stack<T>::top() 45 { 46 if (top_ + 1 == 0) 47 throw out_of_range("stack<>::top() stack empty"); 48 return elem_[top_]; 49 } 50 template<typename T> 51 const T& Stack<T>::top() const 52 { 53 if (top_ + 1 == 0) 54 throw out_of_range("stack<>::top() stack empty"); 55 return elem_[top_]; 56 } 57 template<typename T> 58 bool Stack<T>::empty() const 59 { 60 return top_ + 1 == 0; 61 } 62 63 #include<iostream> 64 #include "Stack.h" 65 using namespace std; 66 67 68 int main(void) 69 { 70 Stack<int> s(10); 71 s.push(1); 72 s.push(2); 73 s.push(3); 74 while (!s.empty()) 75 { 76 cout << s.top() << endl; 77 s.pop(); 78 } 79 return 0; 80 }
下面对上述类模板进行改进,引入非类型参数:
#pragma once #include<exception> //类模板也可以传递非类型参数 template <typename T,int MAX_SIZE> class Stack { public: Stack(); ~Stack(); void push(const T& elem); void pop(); T& top(); const T& top() const; bool empty() const; private: T* elem_; //int maxSize_;//栈最大元素个数 int top_;//保存栈顶位置 }; template <typename T, int MAX_SIZE> Stack<T,MAX_SIZE>::Stack() :top_(-1) { elem_ = new T[MAX_SIZE]; } template <typename T, int MAX_SIZE> Stack<T, MAX_SIZE>::~Stack() { delete[] elem_; } template <typename T, int MAX_SIZE> void Stack<T, MAX_SIZE>::push(const T& elem) { if (top_ + 1 >= MAX_SIZE) throw out_of_range("stack<>::push satck full"); elem_[++top_] = elem; } template <typename T, int MAX_SIZE> void Stack<T, MAX_SIZE>::pop() { if (top_ + 1 <= 0) throw out_of_range("stack<>::pop stack empty"); --top_; } template <typename T, int MAX_SIZE> T& Stack<T, MAX_SIZE>::top() { if (top_ + 1 == 0) throw out_of_range("stack<>::top() stack empty"); return elem_[top_]; } template <typename T, int MAX_SIZE> const T& Stack<T, MAX_SIZE>::top() const { if (top_ + 1 == 0) throw out_of_range("stack<>::top() stack empty"); return elem_[top_]; } template <typename T, int MAX_SIZE> bool Stack<T,MAX_SIZE>::empty() const { return top_ + 1 == 0; }
进一步,类模板还可以传递内部数据类型。类似于适配器。如下面的例子:
1 #pragma once 2 #include<exception> 3 #include<deque> 4 using namespace std; 5 //类模板可以传递内部数据类型.适配器 6 //代码复用不是通过继承,而是通过适配 7 template <typename T,typename CONT=deque<T> > 8 class Stack 9 { 10 public: 11 Stack() :c_() {} 12 ~Stack() {} 13 void push(const T& elem) 14 { 15 c_.push_back(elem); 16 } 17 void pop() 18 { 19 c_.pop_back(); 20 } 21 T& top() 22 { 23 return c_.back(); 24 } 25 const T& top() const 26 { 27 return c_.back(); 28 } 29 bool empty() const 30 { 31 return c_.empty(); 32 } 33 private: 34 CONT c_; 35 }; 36 37 38 #include"Stack.h" 39 #include<iostream> 40 #include<vector> 41 int main() 42 { 43 //Stack<int> s; 44 Stack<int, vector<int> >s; 45 s.push(1); 46 s.push(2); 47 s.push(3); 48 while (!s.empty()) 49 { 50 cout << s.top() << endl; 51 s.pop(); 52 } 53 return 0; 54 }