类模板声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //通常形式 template < typename TypeParam> class SomeClass { //...SomeClass的成员 }; //或者 template < typename TypeParam1,..., typename TypeParamn> class SomeClass { //...SomeClass的成员 }; |
在这些形式中,TypeParam是命名将要存储在容器类SomeClass中的数据的类型的通用类型參数,而关键词typename能够被替换为class。
注意
1.关键词template规定了后面接着的是一个类的模式,而不是一个实际的类声明
2.在类型形參列表中关键词tpyename和class能够互换使用
3.和规则类的函数成员不同,在使用类模板时,编译器必须可以找到他的函数成员的定义。一种通常的方法是将全部函数定义从实现文件ClassName.cpp中移到ClassName.h中类声明后面。还有一种方法是将函数定义放在单独的文件里然后再ClassName.h的最后#include这个文件。
一个类模板不过描写叙述怎样依据给定的类型那个构建不同的类的一个模式,这个创建一个类的过程被称为实例化。这是通过附加一个实际类型到对象定义中的类名上来实现的:
1 | SomeClass<Actual_Type> object; |
比如,能够使用以下的定义来实例化Stack这个类模板:
1 2 | Stack< char > charStack; Stack< char > dubStack; |
当编译器处理这些声明时,他将产生两个不同的Stack类(两个实例),一个是使用char取代了StackElement,还有一个是使用double取代了StackElement。第一个类中的构造函数将构造charStack为一个空的字符型的栈,而第二个类中的构造函数将构造dubStack为一个空的double型的栈。
有3条重要的规则规定了怎样创建类模板:
1.全部定义在类声明之外的操作都必须是模板函数
2.不论什么将一个模板类的名作为类型的使用都必须參数化
3.当使用类模板时,编译器必须可以找到它的操作的定义
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 | template < typename StackElement> class Stack { //复制构造函数 Stack( const Stack<StackElement>& original); //赋值运算符 const Stack<StackElement>& operator=( const Stack<StackElement>& original); //somecode }; template < typename StackElement> Stack<StackElement>::Stack() { // 构造函数的定义 } template < typename StackElement> Stack<StackElement>::Stack( const Stack<StackElement>& original) { //复制构造函数 } //---operator<<() template < typename StackElement> inline ostream& operator<<(ostream& out, const Stack<StackElement>& st) { //somecode } |
一个Stack类模板
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 | #include <iostream> #include <cassert> using namespace std; #ifndef DSTACK #define DSTACK template < typename StackElement> class Stack { public : Stack( int numElements = 128); Stack( const Stack<StackElement>& original); ~Stack(); const Stack<StackElement>& operator =( const Stack<StackElement>& rightHandSide); bool empty() const ; void push( const StackElement& value); void display(ostream& out) const ; StackElement top() const ; void pop(); private : int myCapacity; int myTop; StackElement* myArray; }; |
相应的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 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 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include <new> template < typename StackElement> Stack<StackElement>::Stack( int numElements) { assert (numElements>0); myCapacity = numElements; myArray = new ( nothrow ) StackElement[myCapacity]; if (myArray != 0) myTop = -1; else { cerr << "Inadequate memort to allocate stack !\n" << " -- terminating execution !\n" ; exit (1); } } template < typename StackElement> Stack<StackElement>::Stack( const Stack<StackElement> &original):myCapacity(original.myCapacity),myTop(original.myTop) { myArray = new ( nothrow ) StackElement[myCapacity]; if (myArray != 0) for ( int pos=0;pos<=myTop;pos++) myArray[pos] = original.myArray[pos]; else { cerr << "Inadequate memort to allocate stack !\n" ; exit (1); } } template < typename StackElement> inline Stack<StackElement>::~Stack() { delete [] myArray; } template < typename StackElement> const Stack<StackElement>& Stack<StackElement>::operator =( const Stack<StackElement>& rightHandSide) { if ( this != &rightHandSide) { if (myCapacity != rightHandSide.myCapacity) { delete [] myArray; myCapacity = rightHandSide.myCapacity; myArray = new StackElement[myCapacity]; if (myArray == 0) { cerr << "Inadequate memory !\n" ; exit (1); } } myTop = rightHandSide.myTop; for ( int pos=0;pos<=myTop;pos++) myArray[pos] = rightHandSide.myArray[pos]; } return * this ; } template < typename StackElement> inline bool Stack<StackElement>::empty() const { return (myTop == -1); } template < typename StackElement> inline void Stack<StackElement>::push( const StackElement &value) { if (myTop < myCapacity-1) { ++myTop; myArray[myTop] = value; } else { cerr << "Stack full, can't add new value' !\n" ; exit (1); } } template < typename StackElement> inline void Stack<StackElement>::display(ostream &out) const { for ( int i=myTop;i>=0;i--) out << myArray[i] << endl; } template < typename StackElement> inline ostream& operator <<(ostream& out, const Stack<StackElement>& st) { st.display(out); return out; } template < typename StackElement> inline StackElement Stack<StackElement>::top() const { if (!empty()) return (myArray[myTop]); else { cerr << "Stack is empty -- returning garbage value\n" ; StackElement garbage; return garbage; } } template < typename StackElement> inline void Stack<StackElement>::pop() { if (myTop >= 0) myTop--; else cerr << "Stack is empty -- can't remove a value\n" ; } |