当前位置: 首页 > 文档资料 > C++大学教程 >

12.2 函数模板

优质
小牛编辑
127浏览
2023-12-01

重载函数通常是基于不同的数据类型完成类似的操作。如果对每种数据类型的操作是相同的,那么用函数模扳完成这项工作更为简洁和方便。程序员对函数模板的定义只编写一次。基于调用函数时提供的参数类型,C++自动产生单独的目标代码函数来正确地处理每种类型的调用。

在C浯言中,这个任务是用预处理指令#define建立的宏完成的(见第17章)。但是,宏可能会产生副作用,并且使编译器不能进行类型检查。函数模板和宏一样的简洁,并且还能让编译器进行全面的类型检查。

测试与调试提示 12.1
函数模板和宏一样允许软件复用。但与宏不同的是,函数模板还可以消除许多类型错误,因为C++提供了安全的全面类型检查。

所有的函数模板定义都是用关键字template开始的,该关键字之后是用尖括号<>括起来的形式参数表。每一个形式参数之前都有关健字class,例如:

template<class T>

template<class ElementType>

template<class BorderType,class FillType>

内部类型和自定义类型可用来指定传递给函数的参数类型、函数返回类型和声明函数中变量,函数模板中的形式参数的用法与之类似。该函数定义的方式与定义其他函数类似。注意关键字class指定函数模板类型参数,实际上表示“任何内部类型或用户自定义类型”。

常见编程错误 12.1
函数模板的每个形式类型参数之前不放置关键字class(或新的关键字 typename)。

下面看看图 12.1 的 printArray 函数模板,这个函数的用法见图12.2的完整程序。

1 template< class T >
2 void printArray( const T *array, const int count )
3 {
4 for ( int i = 0; i < count; i++ )
5 cout << array [i ] << " ";
6
7 cout << endl;
8 }

图 12. 1 函数模板

该函数模板把惟一的形式参数T(T一般作为类型参数)声明为函数printArray打印的数组类型。当编译器检测到程序源代码中调用函数printArray时,用printArray的第一个参数的类型替换掉整个模板定义中的T,并建立用来打印指定类型数组的一个完整的模板函数,然后再编译这个新建的函数。

图 12.2 的程序演示了三个printArray函数,这三个函数分别需要一个int类型的数组、一个double类型的数组和一个char类型的数组。int类型数组的实例函数如下所示:

void printArray( const int *array, const int count )
{
for (int i = O; i < count; i++ )
cout << array [ i ] <<" ";
count << endl;
}

模板函数中的每一个形式参数要在函数参数表中至少出现一次。形式参数的名字可以只在模板函数的形式参数表中出现一次。同一个形式参数名可用于多个模板函数。
图12.2的程序反映了模板函数printArray的用法。程序首先实例化int数组a、double数组b和char数组c,长度分别为5、7、6。然后调用pfintArray打印每个数组,一次用a的第一个参数,类型为int*;一次用b的第一个参数,类型为double*;一次用c的第一个参数,类型为char*。

例如,下列语句:

printArray(a,aCount);

使编译器实例化printArray模板函数,类型参数T为int。下列语句:

printArray(b,bCount);

使编译器实例化第二个pfintArry模板函数,类型参数T为double。下列语句:

printArray(c,cCount);

使编译器实例化第三个printArray模板函数,类型参数T为char。

本例中,模板机制使程序员不必用下列原型编写三个重载函数:

void printArray( const int*, const int );
void printArray( const double*, const int );
void printArray( const char*, const int );
1 // Fig 12.2: fig12_02.cpp
2 // Using template functions
3 #include <iostream.h>
4
5 template< class T >
6 void printArray( const T *array, const int count )
7 {
8 for (int i = 0; i < count; i++ )
9 cout << array[ i ] <<" ";
10
11 cout << endl;
12}
13
14 int main()
15 {
16 const int aCount = 5, bCount = 7, cCount = 6;
17 int a[ aCount ] = { 1, 2, 3, 4, 5 };
18 double b[ bCount ] = { 1.1, 2.2, 3.3, 4.4, 6.5, 6.6, 7.7 };
19 char c[ cCount ] = "HELLO"; // 6th position for null
20
21 cout << "Array a contains:" << endl;
22 printArray( a, aCount ); // integer template function
23
24 cout << "Array b contains:" << endl;
25 printArray( b, bCount ); // double template function
26
27 cout << "Array c contains:" << endl;
28 printArray( c, cCount ); // character template function
29
30 return 0;
31 }

输出结果:

Array a contains:
1 2 3 4 5
Array b contains:
1.1 2.2 3.3 4.4 5.5 6.6 7.7
Array c contains:
H E L L O

图 12.2 使用模板函数

性能提示 12.1
模板提供了软件复用的好处。请记住,尽管模板只编写一次,但程序中仍然实例化多个模板类的副本。这些副本会占用大量内存。