12.3 类模板

    模板同样可以用在类场合中,提供通用型的类定义。C++标准库中提供了很多模板类,下一章中要讨论的C++标准模板库STL,其基础便是模板,本节先介绍类模板的基础知识。

    12.3.1 定义类模板

    理解了函数模板的应用,类模板的提出便是水到渠成的事,如示例代码12.7所示。

    代码12.7 类模板的定义ClassTemplateDefinition


    <——————————————-文件名:Stack.h————————————————> 01 template<class T,int num>//类型参数表 02 class Stack//Stack类定义 03 { 04 private: 05 T sz[num];//存储空间,用数组表示 06 int point;//指针,表示存储位置(即元素个数) 07 public: 08 Stack();//构造函数 09 bool isEmpty();//判断栈是否为空 10 bool isFull();//判断栈是否已满 11 bool push(const T&);//将一个元素压入栈 12 bool pop(T&);//从栈中弹出一个元素 13 }; 14 template<class T,int num> 15 Stack<T,num>:Stack() 16 { 17 point=0;//初始位置为0,栈底 18 } 19 template<class T1,int num1>//参数列表不要求每个字都相同,但形式要相同 20 bool Stack<T1,num1>:isEmpty() 21 { 22 return point==0;//point为0,说明当前无元素 23 } 24 template<class T,int num> 25 bool Stack<T,num>:isFull() 26 { 27 return point==num;//point为num,说明数组已满 28 } 29 template<class T,int num> 30 bool Stack<T,num>:push(const T&obt) 31 { 32 if(isFull()) 33 return false;//如果栈已满,压入不成功,返回false 34 else 35 { 36 sz[point]=obt;//将传入的元素存储在point指向的当前位置 37 point++;//point加1,向栈顶移动 38 return true;//压入成功,返回true 39 } 40 } 41 template<class T,int num> 42 bool Stack<T,num>:pop(T&obt) 43 { 44 if(isEmpty()) 45 return false;//如果栈已空,无法弹出,返回false 46 else 47 { 48 point—;//point减1,向栈底移动,指向存储的最上面一个元素 49 obt=sz[point];//将point指向的当前位置元素复制给传入参数 50 return true;//弹出成功,返回true 51 } 52 } <———————————-文件名:example1207.cpp———————————————> 53 #include<iostream> 54 #include"Stack.h" 55 using namespace std; 56 int main() 57 { 58 Stack<int,10>st; 59 cout<<"开始时st是否为空?"<<st.isEmpty()<<endl; 60 st. push(5);//压入元素5 61 cout<<"此时st是否为空?"<<st.isEmpty()<<endl; 62 for(int i=1;i<10;i++) 63 { 64 st. push(i);//压入9个元素 65 } 66 cout<<"此时st是否已满?"<<st.isFull()<<endl; 67 int rec=0; 68 while(st. pop(rec)) 69 cout<<rec<<""; 70 cout<<endl; 71 return 0; 72 }

    输出结果如下所示。


    开始时st是否为空?1 此时st是否为空?0 此时st是否已满?1 9 8 7 6 5 4 3 2 1 5

    【代码解析】代码第2~52行,相对完整地实现了一个栈类Stack,列出了类模板和成员函数模板。模板的引入使得类的定义更为灵活,可以在类创建时指明其中的元素类型T,以及非类型常量num的大小,需要注意的是不管是类定义还是成员函数定义,都要遵守模板的定义形式。

    注意

    类模板和成员函数模板不是传统意义上的类定义和成员函数定义,它们是C++编译指令,用以向编译器说明如何生成类定义和成员函数定义。example1207中调用“Stack<int,10>st;”生成对象的操作称为实例化(Instantiation)或具体化(Specialization)。

    原则上,类模板和成员函数模板要放在同一个文件中,不能像普通的类一样将类定义放在一个文件中,成员函数的实现可以放在另一个文件中,这是因为模板不是函数,不能被单独编译。最简单的方法是像代码12.7中那样将所有的模板信息放在头文件中,只要在使用这些模板的文件中包含该头文件即可。

    当然,如果在类模板和函数模板定义时使用export关键字进行修饰,类模板和成员函数模板可以分开来,这种功能在当前的VC编译器(包括VC 2005)中尚不支持。