C++基础知识之"函数模板"

fengjingtu

为什么要有函数模板

需求:写n个函数,交换char类型、int类型、double类型变量的值。

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
#include<iostream>
using namespace std;

//函数模板与类模板的编程也叫作泛型编程
//函数模板就是一个通用函数
//数据类型参数化,参数的多态性,称为类属,参数模板
template <typename T>
void swapT(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
return;
}
template <typename T>
void printT(T &a, T &b)
{
cout << a << "," << b << endl;
return;
}

void main_fun_template()
{
int a1 = 1;
int b1 = 2;
printT(a1, b1);
swapT(a1, b1);
printT(a1, b1);
char a2 = 'a';
char b2 = 'b';
printT(a2, b2);
swapT(a2, b2);
printT(a2, b2);
double a3 = 3.5;
double b3 = 3.6;
printT(a3, b3);
swapT(a3, b3);
printT(a3, b3);
system("pause");
return ;

}

函数模板语法

函数模板定义形式
template <类型形式参数表>
类型形式参数的形式为:
typename T1,typename T2, …… ,typename Tn
或者:
class T1,classT2, …… ,class Tn

函数模板定义由模板说明和函数定义组成

模板说明的类属参数必须在函数定义中至少出现一次

函数参数表中可以使用类属类型参数,也可以使用一般类型参数

函数模板的调用形式:

1
2
myswap<float>(a,b);//显示类型调用
myswap(a,b); //自动数据类型推导

函数模板做函数参数

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
47
48

#include<iostream>
using namespace std;
//函数模板做函数参数
template <typename T,typename T2>
void sortArray(T *a, T2 num)
{
T temp;
int i;
int j;
for (i = 0; i < num; i++)
{
for (j = i + 1; j < num; j++)
{
if (a[i] < a[j])
{
temp = a[i];
a[i] = a[j];
a[j] = temp;

}
}
}
}
template <typename T, typename T2>
void printArray(T *a, T2 num)
{
int i = 0;
for (i = 0; i < num; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
void test_template_fun1()
{
int a[10] = { 1,3,2,5,6,8,7,4,0,9 };
char b[]= "ambgiysgrxk";

printArray<int,int>(a, (sizeof(a)/sizeof(*a)));
sortArray<int,int>(a, (sizeof(a) / sizeof(*a)));
printArray<int,int>(a, (sizeof(a) / sizeof(*a)));

printArray<char,int>(b, strlen(b));
sortArray<char,int>(b, strlen(b));
printArray<char,int>(b, strlen(b));

}

函数模板遇上函数重载

函数模板不允许自动类型转化
普通函数能够进行自动类型转换

1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配,那么选择模板
4 可以通过空模板实参列表的语法限定编译器只通过模板匹配

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
//函数模板遇上函数重载

void sortArray(int *a, int num)
{
int temp;
int i;
int j;
for (i = 0; i < num; i++)
{
for (j = i + 1; j < num; j++)
{
if (a[i] < a[j])
{
temp = a[i];
a[i] = a[j];
a[j] = temp;

}
}
}
}
void test_template_fun2()
{
int a[10] = { 1,3,2,5,6,8,7,4,0,9 };
char b[] = "ambgiysgrxk";
sortArray(a,10);//优先选择普通函数
sortArray(a, (sizeof(a) / sizeof(*a)));//函数模板匹配的更好,不需要unsigned转int,选择函数模板
sortArray<>(a,10);//有空模板实参列表,一定使用模板
}

函数模板机制

编译器并不是把函数模板处理成能够处理任意类的函数

编译器从函数模板通过具体类型产生不同的函数

编译器会对函数模板进行两次编译

在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。