
2.3 标准模板库
2.3.1 模板的基本概念
标准模板库(Standard Template Library,STL)可以说是基于模板(Template)而建立的。因此我们先简要介绍模板的基本概念及使用方法。
模板是实现代码重用机制的一种工具,可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码可重用性。C++是一种“强类型”的语言,即编译器必须确切地知道变量的类型,而模板就是构建在这个强类型语言基础上的泛型系统。
我们先看一个示例程序。
程序2-9 整型取较大值函数

函数GetMax()返回两个整数中的较大值。但是在一个实际应用程序中可能还需要处理float、long、char等类型的变量,甚至是自定义类型(如结构体)的变量。针对不同的参数类型,需要把上面代码中的数据类型修改为特定类型,然后复制到需要的地方。这种设计方法会给代码维护带来很大的困扰,如代码量增大,修改时需要对多处代码进行修改。解决这个问题的方法之一是使用模板。
模板包括函数模板(Function Template)和类模板(Class Template)两种,下面分别介绍函数模板和类模型的定义和使用。
函数模板(Function Template)用于定义和生成通用的函数,这些函数能够接受任意数据类型的参数,可返回任意类型的值,而不需要对所有可能的数据类型进行函数重载。这在一定程度上实现了宏(Macro)的作用。它们的原型定义可以是下面的任何一个。

例如,下面代码定义了一个模板,它返回两个对象中较大的一个。
程序2-10 取较大值的函数模板

程序2-10中的第一行声明一个通用数据类型,称为GenericType。因此在其后面的函数中,GenericType成为一个有效的数据类型,被用来定义两个参数a和b,并被用于函数GetMax的返回值类型。在定义时,GenericType没有代表任何具体的数据类型。当函数GetMax被调用的时候,我们可以使用任何有效的数据类型来调用它。这个数据类型将被作为模式(Pattern)来代替函数中GenericType出现的地方。
用一个已定义数据类型来调用函数模板的方法如下:

例如,调用GetMax函数比较两个int类型的整数可以这样写:

在编译时,GetMax中所有GenericType 出现的地方都用int 来代替,并构造一个新函数,这个过程称为模板的“特化”。程序2-11演示了函数模板的定义和使用。
程序2-11 函数模板定义和使用示例

注意:为了简洁起见,人们一般用T代替GenericType,表示通用数据类型。
在上面的例子中,我们对同样的函数GetMax使用了两种参数类型:int 和 long,而只写了一种函数的实现,即我们写了一个函数的模板,用了两种不同的模式来调用它。
在函数模板中,如果类型参数可以推导,那么可以省略类型参数表。比如,在程序2-11中,GetMax<int>(i, j)替换为GetMax(i, j)可以得到同样的结果。因为i和j都是int类型,编译器会自动假设我们想要函数按照int进行调用。请读者自己完成验证。
类模板(Class Template)使得一个类可以有基于通用类型的成员,而不需要在类定义的时候确定具体的数据类型。原型定义如下:

template是声明模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个。例如:


上面定义的类可以用来存储两个任意类型的元素组成的有序对。例如:

分别定义了两个类对象:一个存储两个整型数据115和36,另一个存储整数和浮点数对3和2.18。