1,一个类模板至少具有一个类参数,类参数是个符号以表示将要被某个确定数据类型代替的类型。
1 #include<iostream> 2 #include<string> 3 4 using namespace std; 5 6 template <class T> 7 class Array { 8 public: 9 T& operator [](int); 10 const T& operator [](int); 11 Array(int); 12 ~Array(); 13 int get_size() const { return size;} 14 private: 15 char* a; 16 int size; 17 Array(); // 实例化的时候必须给出大小 18 T dummy_val; 19 }; 20 21 template<class T> 22 T& Array<T>::operator [](int i) { 23 if(i < 0 || i >= size) { 24 cerr << "index "<<i<<" out of bounds! "; 25 return dummy_val; 26 } 27 return a[i]; 28 } 29 30 template<class T> 31 T& Array<T>::operator [](int i) const { 32 if(i < 0 || i >= size) { 33 cerr << "index "<<i<<" out of bounds! "; 34 return dummy_val; 35 } 36 return a[i]; 37 } 38 39 template<class T> 40 Array<T>::Array(int s) { 41 a = new T[size = s]; 42 } 43 44 template<class T> 45 Array<T>::~Array() { 46 delete[] a; 47 } 48 49 template<class T> 50 ostream operator<<(ostream& os,const Array<T>& arr) { // 顶层函数重载 51 for(int i=0;i<arr.get_size();++i) 52 os<<arr[i]<<endl; 53 return os; 54 }
由于 Array 类的参数化构造函数与重载的下标操作符在类声明之外定义,因此需要在定义之前加上模板头:template <class T>。
由于 Array 是个模板类,因此类名是 Array<T>,这里 T 是模板头的类参数。
2,类模板可以拥有多个类参数,这些参数用逗号隔开。每个类参数前都必须有关键字 class 或 typename。
1 template<class T1,class T2,class T3> 2 class Sample { 3 public: 4 T2 m(T3 p) { } // expects a T3 arg,returns a T2 5 private: 6 T1 x; // var of type T1 7 };
3,模板实例:我们通过 < > 中指定数据类型来使用一个模板类。
1 int main() { 2 Array<int> a1(10); // Array of 10 int 3 4 return 0; 5 }
以上语法表面用 int 来替换模板类 Array 声明的类参数 T,编译器会将在 Array 声明中所有的类参数 T 替换成 int。
用内建的或自定义的数据类型都可以创建模板实例
1 class Task { // user-defined data type 2 //... 3 }; 4 5 Array<Task> tasks(10);
4,一个对象不能属于像 Array 或 Array<T> 的对象,但我们可以定义类型为 Array<int> 的对象。
5,参数表中的类模板:类模板可以作为一种数据类型出现在参数表中。
1 template<class T> 2 ostream operator<<(ostream& os,const Array<T>& arr) { // 顶层函数重载 3 for(int i=0;i<arr.get_size();++i) 4 os<<arr[i]<<endl; 5 return os; 6 }
6,模板的函数式参数:类模板必须至少有一个类参数,当然可以有多个类参数。类模板、还可以有非类参数的参数,一般称之为函数类型参数,一个模板类可以有多个函数类型参数,所有的参数用逗号分开。
1 template<class T,int x,float Y> 2 class Sample { 3 //... 4 };
7,示例程序:模板堆栈类
1 // stack 2 template<class T> 3 class Stack { 4 public: 5 enum{ DefaultSize = 50,EmptyStack = -1}; 6 Stack(); 7 Stack(int); 8 ~Stack(); 9 void push( const T&); 10 T pop(); 11 T getNoPop() const; 12 bool empty() const; 13 bool full() const; 14 private: 15 T* elements; 16 int top; 17 int size; 18 void allocate() { 19 elements = new T[size]; 20 top = EmptyStack; 21 } 22 void msg(const char* m) const { 23 cout << "***** "<<m<<" *****"<<endl; 24 } 25 template<class T> 26 friend ostream& operator<<(ostream& os,const Stack<T>&); 27 }; 28 29 // Stack 类的实现 30 template<class T> 31 Stack<T>::Stack() { 32 size = DefaultSize; 33 allocate(); 34 } 35 36 template<class T> 37 Stack<T>::Stack(int s) { 38 if(s < 0) 39 s *= -1; 40 else if(s == 0) 41 size = DefaultSize; 42 size = s; 43 allocate(); 44 } 45 46 template<class T> 47 Stack<T>::~Stack() { 48 delete[] elements; 49 } 50 51 template<class T> 52 void Stack<T>::push(const T& e) { 53 assert(!full()); 54 if(!full()) 55 elements[++top] = e; 56 else 57 msg("Stack full!"); 58 } 59 60 template<class T> 61 T Stack<T>::pop() { 62 assert(!empty()); 63 if(!empty()) 64 return elements[top--]; 65 else { 66 msg("Stack empty!"); 67 T dummy_val; 68 return dummy_val; // 返回一个不确定的值 69 } 70 } 71 72 template<class T> 73 T Stack<T>:: getNoPop() const { 74 assert(top > EmptyStack); 75 if(!empty) 76 return elements[top]; 77 else { 78 msg("Stack empty!"); 79 T dummy_val; 80 return dummy_val; 81 } 82 } 83 84 template<class T> 85 bool Stack<T>::empty() const { 86 return top <= EmptyStack; 87 } 88 89 template<class T> 90 bool Stack<T>::full() const { 91 return top + 1 >= size; 92 } 93 94 template<class T> 95 ostream& operator<<(ostream& os,const Stack<T>& s) { 96 s.msg("Stack contents:"); 97 int t = s.top; 98 while(t > s.EmptyStack) 99 cout<<s.elements[t--]<<endl; 100 return os; 101 } 102 103 int main() { 104 Stack<int> stk(1); 105 stk.push(1); 106 cout<<stk<<endl; 107 108 return 0; 109 }
8,函数模板
1 #include <iostream> 2 #include <stack> 3 using namespace std; 4 5 // this is a function template 6 template<class Type> 7 Type maxValue(Type a,Type b) { 8 return a > b ? a : b; 9 } 10 11 int main(){ 12 stack<int> intStack; // 类模板的实例化只能由程序员显式指定 13 cout <<"模板函数隐式调用:" << maxValue(1,2) << endl; 14 cout << "模板函数显式调用:" << maxValue<double>(1.1,2.2) <<endl; 15 return 0; 16 }
note:类模板只能通过显式的调用生成模板类; 函数模板可以通过显式调用或隐式调用生成模板函数。