C++程序设计 湖南大学 杜四春、银红霞
第 12章 模板
12.1 模板的概念
12.2 函数模板
12.3 类模板
12.4 模板应用实例
C++程序设计 湖南大学 杜四春、银红霞
模板是 C++支持参数化多态的工具,使用
模板可以使用户为类或者函数声明一种一般模
式,使得类中的某些数据成员或者成员函数的
参数、返回值取得任意类型。
C++程序设计 湖南大学 杜四春、银红霞
12.1 模板的概念
所谓模板是一种使用无类型参数来产生一系列函
数或类的机制, 是 C++的一个重要特性 。 它的实现,
方便了更大规模的软件开发 。
若一个程序的功能是对某种特定的数据类型进行
处理,则可以将所处理的数据类型说明为参数,以便
在其他数据类型的情况下使用,这就是模板的由来。
模板是以一种完全通用的方法来设计函数或类而不必
预先说明将被使用的每个对象的类型。通过模板可以
产生类或函数的集合,使它们操作不同的数据类型,
从而避免需要为每一种数据类型产生一个单独的类或
函数。
C++程序设计 湖南大学 杜四春、银红霞
例如, 设计一个求两参数最大值的函数, 不使用
模板时, 需要定义四个函数:
int max(int a,int b){return(a>b)?a,b;}
long max(long a,long b){return(a>b)?a,b;}
double max(double a,double b){return(a>b)?a,b;}
char max(char a,char b){return(a>b)?a,b;}
若使用模板, 则只定义一个函数:
Template<class type>type max(type a,type b)
{return(a>b)?a,b;}
C++程序设计 湖南大学 杜四春、银红霞
C++程序由类和函数组成, 模板也分为类模板
( class template) 和函数模板 ( function template) 。 在
说明了一个函数模板后, 当编译系统发现有一个对应
的函数调用时, 将根据实参中的类型来确认是否匹配
函数模板中对应的形参, 然后生成一个重载函数 。 该
重载函数的定义体与函数模板的函数定义体相同, 它
称之为模板函数 ( template function) 。
同样,在说明了一个类模板之后,可以创建类模
板的实例,即生成模板类。
C++程序设计 湖南大学 杜四春、银红霞
12.2 函数模板
C++提供的函数模板可以定义一个对任何类型变
量进行操作的函数, 从而大大增强了函数设计的通用
性 。 使用函数模板的方法是先说明函数模板, 然后实
例化成相应的模板函数进行调用执行 。
12.2.1 函数模板说明
函数模板的一般说明形式如下:
template < 模板形参表 >
<返回值类型 ><函数名 >( 模板函数形参表 )
{
//函数定义体
}
C++程序设计 湖南大学 杜四春、银红霞
其中, <模板形参表 >可以包含基本数据类型, 也
可以包含类类型 。 类型形参需要加前缀 class。 如果类
型形参多于一个, 则每个类型形参都要使用 class。 <模
板函数形参表 >中的参数必须是惟一的, 而且 <函数定
义体 >中至少出现一次 。
函数模板定义不是一个实实在在的函数,编译系
统不为其产生任何执行代码。该定义只是对函数的描
述,表示它每次能单独处理在类型形式参数表中说明
的数据类型。
C++程序设计 湖南大学 杜四春、银红霞
#include <iostream.h>
template <class T>
T min(T a[],int n)
{
int i;
T minv=a[0];
for(i=1;i<n;i++)
if(minv>a[i])
minv=a[i];
return minv;
}
例 12-1:编写一个对具有 n个元素的数组 a[ ]求最小值的程
序,要求将求最小值的函数设计成函数模板。
void main()
{ ina a[]={1,3,0,2,7,6,4,5,2};
double b[]={1.2,-3.4,6.8,9,8};
cout<<”a数组的最小值为:,
<<min(a,9)<< endl;
cout<<”b数组的最小值为:,
<<min(b,4)<<endl; }
此程序的运行结果为:
a数组的最小值为,0
b数组的最小值为,-3.4
C++程序设计 湖南大学 杜四春、银红霞
12.2.2 使用函数模板
函数模板只是说明, 不能直接执行, 需要实例化
为模板函数后才能执行 。
当编译系统发现有一个函数调用,<函数名 >( <实
参表 >) ;时, 将根据 <实参表 >中的类型生成一个重载
函数即模板函数 。 该模板函数的定义体与函数模板的
函数定义体相同, 而 <形参表 >的类型则以 <实参表 >的
实际类型为依据 。
在模板函数被实例化之前,必须在函数的某个地
方首先说明它(可能不进行定义),这样,就可以到
后面再定义模板。和一般函数一样,如果函数模板的
定义在首次调用之前,函数模板的定义就是对它的说
明。定义之后的首次调用就是对模板函数的实例化。
C++程序设计 湖南大学 杜四春、银红霞
对模板函数的说明和定义必须是全局作用域 。 模
板不能被说明为类的成员函数 。
模板函数有一个特点,虽然模板参数 T可以实例化
成各种类型,但是采用模板参数 T的各参数之间必须保
持完全一致的类型。模板类型并不具有隐式的类型转
换,例如在 int与 char之间,float与 int之间,float与
double之间等的隐式类型转换。而这种转换在 C++中是
非常普遍的。
例 12-2:函数模板仅定义了函数的形状, 编译器将
根据实际的数据类型参量在内部产生一个相应的参数
模板, 一个模板函数的数据类型参量必须全部使用模
板形参 。
C++程序设计 湖南大学 杜四春、银红霞
函数模板方法克服了 C语言解决上述问题时用大量
不同函数名表示相似功能的坏习惯;克服了宏定义不
能进行参数类型检查的弊端;克服了 C++函数重载用
相同函数名字重写几个函数的繁琐。因而,函数模板
是 C++中功能最强的特性之一,具有宏定义和重载的
共同优点,是提高软件代码重用率的重要手段。
C++程序设计 湖南大学 杜四春、银红霞
12.2.3 重载模板函数
模板函数与普通函数一样, 也可以重载 。
例 12-3:
程序中函数 char max( char *,char *) 中的名字与
函数模板的名字相同, 但操作不同, 函数体中的比较
采用了字符串比较函数, 这就是模板函数的重载 。 编
译器在处理时, 首先匹配重载函数, 然后再寻求模板
的匹配 。
C++程序设计 湖南大学 杜四春、银红霞
12.3 类模板
类模板与函数模板类似, 它可以为各种不同的数
据类型定义一种模板, 在引用时使用不同的数据类型
实例化该类模板, 从而形成一个类的集合 。
类模板实际上是函数模板的推广 。 可以用相同的
类模板来组建任何类型的对象集合 。 在传统 C++中,
可能有一个浮点数类或者一个整数类, 如果使用类模
板, 可以定义一个对两者都适用的类 number。
12.3.1 类模板说明
类模板说明的一般形式是:
C++程序设计 湖南大学 杜四春、银红霞
template <类型形参表 >
class <类名 >
{ //类说明体 };
template <类型形参表 >
<返回类型 ><类名 ><类型名表 >::<成员函数 1>( 形参表 )
{ //成员函数定义体 }
template <类型形参表 >
<返回类型 ><类名 ><类型名表 >::<成员函数 2>( 形参表 )
{ //成员函数定义体 }

template <类型形参表 >
<返回类型 ><类名 ><类型名表 >::<成员函数 n>( 形参表 )
{ //成员函数定义体 }
C++程序设计 湖南大学 杜四春、银红霞
其中的 <类型形参表 >与函数模板中的意义一样 。
后面的成员函数定义中, <类型名表 >是类型形参的使
用 。
这样的一个说明 ( 包括成员函数定义 ) 不是一个
实实在在的类, 只是对类的描述, 称为类模板 ( class
template) 。 类模板必须用类型参数将其实例化为模板
类后, 才能用来生成对象 。 一般地, 其表示形式为:
类模板名 <类型实参 > 对象名 ( 值实参表 )
其中类型实参表表示将类模板实例化为模板类时
所用到的类型(包括系统固有的类型和用户已定义类
型),值实参表表示将该模板类实例化为对象时其构
造函数所用到的变量。一个类模板可以用来实例化多
个模板类。
C++程序设计 湖南大学 杜四春、银红霞
<类型形参表 >中的形参要加上 class关键词, 类型
形参可以是 C++中的任何基本的或用户定义的类型 。
对在形参表中定义的每个类型, 必须要使用关键词
class。 如果类型形参多于一个, 则每个形参都要使用
关键词 class。
<类型形参表 >也可以包含表达式参数,表达式参
数经常是数值。对模板类进行实例化时给这些参数所
提供的变量必须是常量表达式。类模板参数列表决不
能是空的,如果其中有一个以上的参数,则这些参数
必须要用逗号分开。
C++程序设计 湖南大学 杜四春、银红霞
如:
template <class T1,int exp1,class T2>
class someclass
{
//
};
类模板 someclass的第二个参数是表达式,而第一
和第三个参数是占位符。
类模板的成员函数的体外,每个前面都必须用与
声明该类模板一样的表示形式加以声明,其他部分同
一般的成员函数定义。
C++程序设计 湖南大学 杜四春、银红霞
12.3.2 使用类模板
与函数模板一样, 类模板不能直接使用, 必须先
实例化为相应的模板类, 定义该模板类的对象后才能
使用 。
建立类模板后, 可用下列方式创建类模板的实例:
<类名 ><类型实参表 ><对象表 >;
其中, <类型实参表 >应与该类模板中的 <类型形
参表 >匹配 。 <类型实参表 >是模板类 ( template
class), <对象 >是定义该模板类的一个对象 。
使用类模板可以说明和定义任何类型的类。这种
类被称为参数化的类。如果说类是对象的推广,那么
类模板可以说是类的推广。
注意:类模板与模板类的区别 。
C++程序设计 湖南大学 杜四春、银红霞
12.4 模板应用实例
例 12-7
例 12-8