类模板声明


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"​​​​;​


​}​