当需要对不同的类型使用同一种算法(同一个函数体)时,为了避免定义多个功能重复的函数,可以使用模板。然而,并非所有的类型都使用同一种算法,有些特定的类型需要单独处理,为了满足这种需求,C++
允许对函数模板进行重载,程序员可以像重载常规函数那样重载模板定义。
比如,交换两个变量的值,有两个方法,一个是使用指针,另一个是使用引用:
1 2 3 4 5 6 7 8 9 10 11 12 13 template <typename T> void Swap (T *a, T *b) { T temp = *a; *a = *b; *b = temp; } template <class T> void Swap (T &a, T &b) { T temp = a; a = b; b = temp; }
这两种方案都可以交换 int、float、char、bool
等基本类型变量的值,但是却不能交换两个数组。
对于方案1,调用阿函数时传入的是数组指针,或者说是指向第 0
个元素的指针,这样交换的仅仅是数组的第 0
个元素,而不是整个数组。数组和指针本来是不等价的,只是当函数的形参为指针时,传递的数组也会隐式地转换为指针。
对于方案2,假设传入的是一个长度为 3 的 int 类型数组(该数组的类型是
int[3]
),那么 T 的真实类型为
int[3]
,T temp
会被替换为
int [3]temp
,这显然是错误的。另外一方面,语句
a=b;
尝试对数组 a
赋值,而数组名是常量,它的值不允许被修改,所以也会产生错误。
交换两个数组唯一的办法就是逐个交换所有的数组元素,请看下面的代码:
1 2 3 4 5 6 7 8 template <typename T> void Swap (T a[], T b[], int len) { T temp; for (int i = 0 ; i < len; i++) { temp = a[i]; a[i] = b[i]; b[i] = temp; } }
在该函数模板中,最后一个参数的类型为具体类型(int),而不是泛型。并不是所有的模板参数都必须被泛型化。
下面是一个重载函数模板的完整示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <iostream> using namespace std;template <class T> void Swap (T &a, T &b) ; template <typename T> void Swap (T a[], T b[], int len) ; template <typename T> void printArray (T arr[], int len) ; int main () { int m = 10 , n = 99 ; Swap (m, n); cout << m << ", " << n << endl; int a[3 ] = {1 , 2 , 3 }; int b[3 ] = {4 , 5 , 6 }; int len = sizeof (a) / sizeof (int ); Swap (a, b, len); printArray (a, len); printArray (b, len); return 0 ; } template <class T> void Swap (T &a, T &b) { T temp = a; a = b; b = temp; } template <typename T> void Swap (T a[], T b[], int len) { T temp; for (int i = 0 ; i < len; i++) { temp = a[i]; a[i] = b[i]; b[i] = temp; } } template <typename T> void printArray (T arr[], int len) { for (int i = 0 ; i < len; i++) { cout << arr[i] << ", " ; } cout << endl; }
输出:
1 2 3 99, 10 4, 5, 6, 1, 2, 3,