You are on page 1of 13

C

+
+
第 10 章 类模板



学习目标

1. 理解类模板的概念;
2. 掌握类模板的定义、实例化过程,会运用类模板;
3. 掌握栈类模板、链表类模板的使用。


1 10.1 类模板
0
章 类模板 是能根据不同参数建立不同类型成员的类。类模板中的数据成员、成员
类 函数的参数、成员函数的返回值可以取不同类型,在实例化成对象时,根据传入的
模 参数类型,实例化成具体类型的对象。类模板也称模板类。

C
+ 1. 类模板的 定义
+
培 类模板定义的语法为:
训 template < 模板参 数表 >

class 类名

{
成员 名;
};

其中:
 template 为模板关键字。

1  模板参数表中的类型为参数化 (parameterized) 类型,也称可变类型,类型名
0 为 class ( 或 typename) ;模板参数表中的类型也可包含普通类型,普通类型的参
章 数用来为类的成员提供初值。
 类模板中的成员函数可以是函数模板,也可以是普通函数。



C
+ 1. 类模板的定 义
+
培 例如,下面定义了一个模板类 Student ,为了增强类的适用性,将学
训 号设计成参数化类型,它可以实例化成字符串、整型等;将成绩设计成参数化类
教 型,它可以实例化成整型、浮点型、字符型 ( 用来表示等级分 ) 等;

template <class TNO, class TScore, int num> // TNO,TScore 为参数化类型
class Student
{
private:
TNO StudentID[num]; // 参数化类型数组,存储姓名
TScore score[num]; // 参数化类型数组,存储分数
public:
第 TNO TopStudent() // 普通函数
1 {
0 return StudentID[0];
章 }
int BelowNum(TScore ascore) // 函数模板
类 {
模 return 0;
}
板 void sort() // 普通函数
{
}
};
C
+ 1. 类模板的定 义
+
template <class TNO, class TScore, int num>
培 class模板类的成员函数还可以在类外定义,其语法如下:
Student
训 {
教 template < 模板参 数表 >
private:
程 类型 TNO StudentID[num];
类名 < 模板参 数名 表 > :: 函数名 ( 参数表 )
TScore score[num];
{
public:
TNO函数 体;
TopStudent();
} int BelowNum(TScore ascore);
void sort();
};
其中:<class TNO, class TScore, int num>
template
 int模板参数表与类模板的模板参数表相同;
Student<TNO, TScore, num>::BelowNum(TScore ascore)

1  { 模板参数名表列出的是模板参数表中参数名,顺序与模板参数表中的顺序一致;
return 0;
0 }例如,模板类 Student 的成员函数在类外实现如下:
章 template <class TNO, class TScore, int num>
void Student<TNO, TScore, num>::sort()
类 {
模 }
板 template <class TNO, class TScore, int num>
TNO Student<TNO, TScore, num>::TopStudent()
{
return StudentID[0];
}
C
+
2. 类模板 的实例化
+ 一个类模板是具体类的抽象,在使用类模板建立对象时,才根据给定的
培 模板参数值实例化 ( 专门化 ) 成具体的类,然后由类建立对象。与函数模板不同,

类模板实例化只能采用显式方式。


类模板实例化、建立对象的语法如下 :
类模板 名 < 模板参 数值表 > 对象 1, 对象 2, …, 对象 n;

其中:
 模板参数值表的值为类型名,类型名可以是基本数据类型名,也可以是构造数
据类型名,还可以是类类型名。
第 模板参数值表的值还可以是常数表达式,以初始化模板参数表中普通参数。
1 模板参数值表的值按一一对应的顺序实例化类模板的模板参数表。
0 例如,下面对模板类 Student 实例化 :

class String { 编译 Student<String, float ,100> S1 ;时:
类 public:
模 char Str[20]; String 取代

}; TNO
void main()
{ float 取代 TScore
Student<String, float ,100> S1;
S1.sort(); 100 取代 num
Student<long, int, 50> S2;
S2.TopStudent();
}
C
+ 2. 类模板的实 例化
+
培 template <class TNO, class TScore, 将类 Student 实例化成:
训 int num>
教 class Student class Student

{ {
private: private:
TNO StudentID[num]; String StudentID[100];
TScore score[num]; float score[100];
public: public:
TNO TopStudent() String TopStudent();
第 int BelowNum(TScore ascore) int BelowNum(float ascore);
1 void sort() void sort();
0 }; };




C
+
2. 默认模板 参数
+ 类模板的实例化过程与函数调用的实参与形参结合的过程相似,函数的形
培 参可以采用默认值,类模板的类型参数也可以采用默认值,这样避免每次实例化
训 时都显式给出实参。
教 TScore, num 分别给出默认值 int , 10 。
程 template <class TNO, class TScore=int, 用以下方式实例化: Student<char *>
int num=10> S1;
class Student class Student
{ {
private: private:
TNO StudentID[num]; char * StudentID[10];
第 TScore score[num]; int score[10];
1 public: public:
0 TNO TopStudent(); char * TopStudent();
章 int BelowNum(TScore ascore); int BelowNum(int ascore);
类 void sort(); void sort();
模 }; };

C
+ 10.2 类模板应用
+
培 1. 栈类模板


栈是一种先进后出 FILO(First In Last Out) 的一种结构,在程序设计中广
程 泛使用栈,栈的基本操作有 : 压栈 push 、出栈 pop 。其他操作有判空、判满、读
栈顶元素等。
下图演示栈的操作:
top
u top
z z

top y y
1
0 top x x x

(a) 栈空 (b) 进栈 push(x) (c) 栈满 (d) 出栈 pop()


板 【例 10-1 】栈类模板
分析 :栈空间可以使用静态数组,本例中使用动态数组。使用指针
top 指向栈顶元素,使用成员函数 push() 、 pop() 、 IsEmpty() 、 IsFull() 分别进行
压栈、出栈、判空、判满。
1. 栈类模 板

8 //* p10_1.cpp 栈类模板 33 template <class T>


9 template <class T> 34 Stack <T>::Stack(int size)
C 10 class Stack 35 {
+ 11 { 36 this->size=size;
12 private: 37 space=new T[size];
+ 13 int size; 38 top=size;
培 14 int top; 39 }
训 15 T* space; 40 template <class T>
16 public: 41 bool Stack <T>::push(const T& element)
教 17 Stack(int=10); 42 {
程 18 ~Stack() 43 if(!IsFull())
19 { 44 {
20 delete [] space; 45 space[--top]=element;
21 } 46 return true;
22 bool push(const T&); 47 }
23 T pop(); 48 return false;
24 bool IsEmpty() const 49 }
25 { 50 template <class T>
26 return top==size; 51 T Stack <T>::pop()
27 } 52 {
第 28 bool IsFull() const 53 if(!IsEmpty())
1 29 { 54 return space[top++];
0 30 return top==0; 55 return 0;
31 } 56 }
章 32 }; 57 void main()
58 {
类 59 Stack<char>S1(4);
模 运行结 果 60 S1.push('x');
板 u 61 S1.push('y');
62 S1.push('z');
z 63 S1.push('u');
64 S1.push('v');
y 65 while(!S1.IsEmpty())
x 66 cout<<S1.pop()<<endl;
67 }
C
+ 2. 链表类模板
+
培 【例 10-2 】链表类模板

分析: 链表的操作见 5.5.1 ,为了节省内存空间,将头指针与当前节点

程 指针设计成 static, 为同类型链表所共有;为了便于操作,同样将链表的第一个节点
当成头节点,不存储数据。链表的构成如下图所示:

head head
CurNode CurNode

第 data data ‘A’ ‘B’


1 next NULL next NULL
0

(a) 仅含头节点的空链表 (b) 添加节点后的链表



6 //* p10_2.cpp * 单向链表的类模板 *
7 template <class TYPE>
C 8 class ListNode
9 {
+
2. 链表类模板

10 private:
+ 11 TYPE data;
培 12 ListNode * next;
13 static ListNode * CurNode;
训 14 static ListNode * head;
教 15 public:
程 16 ListNode():next(NULL)
17 { head=CurNode=this; }
20 ListNode(TYPE NewData):data(NewData),next(NULL)
21 { }
23 void AppendNode(TYPE NewNode);
24 void DispList();
25 void DelList();
26 };
27 template <class TYPE>
28 ListNode<TYPE> * ListNode<TYPE>::CurNode;
第 29 template <class TYPE>
1 30 ListNode<TYPE> * ListNode<TYPE>::head;
0 31 template <class TYPE>
32 void ListNode<TYPE>::AppendNode(TYPE NewData) {
章 34 CurNode->next=new ListNode(NewData);
35 CurNode=CurNode->next;
类 36 }
模 37 template <class TYPE>
板 38 void ListNode<TYPE>::DispList(){
40 CurNode=head->next;
41 while(CurNode!=NULL)
42 {
43 cout<<CurNode->data<<endl;
44 CurNode=CurNode->next;
45 }
46 }
47 template <class TYPE> 程序解 释:
48 void ListNode<TYPE>::DelList()
C 49 { 第 16 行为不带参数的构造函数,
+ 50
2. 链表类模板

ListNode *q; 用于建立头节点。第 62 行建立对象


51 CurNode=head->next;
+ 52 while(CurNode!=NULL) 时,调用了不带参数的构造函数,
培 53 { 建立了一个仅含头节点的链表。
训 54 q=CurNode->next;
55 delete CurNode; 第 20 行为带数据域参数的构造函
教 56 CurNode=q; 数,供函数 AppendNode() 动态建
程 57 }
58 head->next=NULL; 立节点对象时调用。
59 } 由于链表的非头节点为动态对象
60 void main()
61 { ,因此,要使用 delete 删除节点,
62 ListNode<char> CList; 以释放内存。
63 CList.AppendNode('A');
64 CList.AppendNode('B');
65 CList.AppendNode('C'); 从上述程序例子可见,类模板是一
第 66 CList.DispList(); 种安全的、高效的重用代码的方式
67 CList.DelList();
1 68 CList.DispList(); ,并可以结合类继承性和函数重载
0 69 } ,实现更大范围类的代码重用。因
章 此,类模板的应用在 C++ 中占有重
类 运行结 果 要的地位。

板 A
B
C
C
+
10.3 本章小结
+



程 ◇ 类模板是能根据不同参数建立不同类型对象的类,类模板中的数据成员、成
员函数的参数、成员函数的返回值可以取参数化类型。
◇ 类模板实例化是在建立对象时,根据传入的参数类型,将类模板实例化成具
体类,然后再建立对象。
◇ 栈是一种先进后出 FILO(First In Last Out) 的一种结构,在程序设计中广泛使
用栈,将栈设计成一个类模板,就可以在栈中存放任意类型的数据。
第 ◇ 动态链表的插入与删除节点的性能优于静态数组,在程序设计中广泛使用链
1 表,将链表设计成一个类模板,就可以在链表节点中存放任意类型的数据。
0