函数模板

函数模板是通用的函数描述,它们使用泛型来定义函数,其中的泛型可用具体的类型替换。通过将类型作为参数传递给模板,可使编译器生成该类型的函数。

1、语法:

template<typename 类型>

返回值类型 函数名(类型 a, 类型 b){}

关键字template和typename是必不可少的,其中typename可用class替换,因为typename是在C++98才引入的,之前都是用class;类型为任意类型,包括自定义类型;

举例:

 1 template<typename T>
 2 void Swap(T& a, T& b)
 3 {
 4     T temp;
 5     temp = a;
 6     a = b;
 7     b = temp;
 8 }
 9 
10 int main()
11 {
12     int a1 = 1, a2 = 2;
13     cout << "a1 = " << a1 << ", a2 = " << a2 << endl;
14     Swap(a1, a2);
15     cout << "a1 = " << a1 << ", a2 = " << a2 << endl;
16 
17     float f1 = 1.1f, f2 = 2.2f;
18     cout << "f1 = " << f1 << ", f2 = " << f2 << endl;
19     Swap(f1, f2);
20     cout << "f1 = " << f1 << ", f2 = " << f2 << endl;
21 
22     return EXIT_SUCCESS;
23 }

结果:

 

2、重载模板:

可以像重载函数那样重载函数模板,和常规重载一样,被重载的模板的函数特征标必须不同。

举例:

 1 const int arrayLen = 4U;
 2 
 3 template<typename T>
 4 void Swap(T& a, T& b)
 5 {
 6     T temp;
 7     temp = a;
 8     a = b;
 9     b = temp;
10 }
11 
12 template<typename T>
13 void Swap(T a[], T b[], int n)
14 {
15     T temp;
16     for (int var = 0; var < n; ++var) {
17         temp = a[var];
18         a[var] = b[var];
19         b[var] = temp;
20     }
21 }
22 
23 void Show(int a[])
24 {
25     cout << a[0] << "," << a[1] << ",";
26     cout << a[2] << "," << a[3] << ",";
27     for (int i = 4; i < arrayLen; i++) {
28         cout << a[i];
29     }
30     cout << endl;
31 }
32 
33 int main()
34 {
35     int i = 10;
36     int j = 20;
37     cout << "i = " << i << ", j = " << j << endl;
38     Swap(i, j);
39     cout << "i = " << i << ", j = " << j << endl;
40 
41     int arr1[arrayLen] = {0, 1, 2, 3};
42     int arr2[arrayLen] = {10, 9, 8, 7};
43     Show(arr1);
44     Show(arr2);
45     Swap(arr1, arr2, arrayLen);
46     Show(arr1);
47     Show(arr2);
48 
49     return EXIT_SUCCESS;
50 }

 

3、模板的局限性

假设有如下模板函数:

template<typename T>

void f(T a, T b)

{a=b;}

当a为数组时这种方式不成立;总之编写的模板函数很可能无法处理某些类型。

类似于上述情况,比较好的解决方式是为特定类型提供具体化的模板定义。

4、显式具体化

函数原型相同,实现算法不同时,可以使用显式具体化提供一个具体化函数定义,当编译器找到与函数调用匹配的具体化定义时,将使用该定义,而不再寻找模板;

<1>对于给定的函数名,可以有非模板函数/模板函数和显示具体化模板函数以及它们的重载版本.

<2>显示具体化的原型和定义应以template<>打头,并通过名称来指出类型.

<3>具体化优先于常规模板,而非模板函数优先于具体化和常规模板.

举例:

 1 template<typename T>
 2 void Swap(T& a, T& b)
 3 {
 4     T temp;
 5     temp = a;
 6     a = b;
 7     b = temp;
 8 }
 9 
10 template<> void Swap<int>(int& a, int& b)
11 {
12     a += 1;
13     b += 1;
14 }
15 
16 int main()
17 {
18     char c1 = 'A', c2 = 'B';
19     cout << "c1 = " << c1 << ", c2 = " << c2 << endl;
20     Swap(c1, c2);
21     cout << "c1 = " << c1 << ", c2 = " << c2 << endl;
22 
23     int i1 = 1, i2 = 2;
24     cout << "i1 = " << i1 << ", i2 = " << i2 << endl;
25     Swap(i1, i2);
26     cout << "i1 = " << i1 << ", i2 = " << i2 << endl;
27 
28 
29     return EXIT_SUCCESS;
30 }

结果:

 

可见char类型的变量使用的是函数模板生成的char类型交换函数,int类型的交换使用的是显示具体化的函数.

5、实例化和具体化

实例化:

定义好函数模板后,编译阶段编译器会根据参数类型进行特定类型的函数定义,这种方式成为隐式实例化;

C++还允许显式实例化,template Swap<int>(int&, int&);注意template后面没有<>,这是和显示具体化的区别;显示的告诉编译器去定义一个参数为int类型的Swap函数;

显示具体化是显示的定义一个和函数模板原型相同但是实现不同的函数;----函数内部实现和模板不同;

显示实例化是显示的定义一个以函数模板为原型的具体类型的函数实现;----函数内部实现和模板相同;

 

posted @ 2022-02-24 22:34  CallMe弱鸡  阅读(293)  评论(0)    收藏  举报