一、函数模板的基本概念
- 函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体的类型(如:int 或double)替换。通过将类型作为参数传递给模板,可使编译器生成该类型的函数。
- 函数模板允许以任意类型的方式来定义函数
第3行指出,要建立一个模板,并将类型命名为T,关键字template是必须的,除非可以使用关键字class代替typename。另外必须使用尖括号。
3.模板并不创建任何函数,而只是告诉编译器如何定义函数,需要交换int的函数时,编译器将按模板模式创建这样的函数,并用int 代替T
4.函数模板类型自推,能够根据参数类型自动推演出类模板类型参数。
5.函数模板不编译,所以即使你在写的时候出错,它也不会给你报错,那么它是怎么出错的呢?在编译期的时候,根据模板调用的类型方式,自动生成一份对应于该类型的代码(也称为模板的实例化)。(也就是上述的第三点)
6.模板的应用场景:需要多个将同一种算法用于不同类型的函数的时候。
二、 .利用代码对上述几点进行解释
- 第一个Swap()函数接受两个int 参数,因此编译器生成该函数的int版本,也就是说,用int替换所有的T,生成了上面中间图片中的定义。我们是根本看不到这些代码的,但是编译器确实生成并在程序中使用了它们。第二个即是把所有的T都用double替换了。
- 注意:函数模板不能缩短可执行程序,最终仍将由两个独立的函数定义,最终的代码不包含任何模板,而只包含了为程序生成的实际函数,使用模板的好处是,它使生成多个函数定义更简单、更可靠
三、重载的模板
需要多个对不同类型使用同一种算法的函数时,可使用模板,然而,并非所有的类型都使用相同的算法,为满足这种需求,可以像重常规函数定义那样重载模板定义。即被重载的模板的函数特征标必须不同。
代码实现:
四、函数模板的特例化
特例化的函数模板的原型和定义都以template<>开头,并通过名称来指出类型
template<> //尖括号内必须为空
void Swap<类型>(类型 形参,类型 形参);
代码实现:
#include<iostream>
using namespace std;
template<typename A>
void show(A &c)
{
cout<<c.name<<'\t'<<c.floor<<'\t'<<c.salary<<endl;
}
struct A
{
char name[40];
double salary;
int floor;
};
template<typename T> //普通模板
void Swap(T &a, T &b)
{
T tmp;
tmp = a;
a = b;
b = tmp;
}
template<>
void Swap<A>(A &a, A &b) //特例化模板
{
double t1;
int t2;
t1 = a.salary;
a.salary = b.salary;
b.salary = t1;
t2 =a.floor;
a.floor = b.floor;
b.floor = t2;
}
int main()
{
A s1 = {"susan",73000.60,7};
A s2 = {"Sindey",35000.90,3};
Swap(s1,s2);
show(s1);
show(s2);
return 0;
}
注:在进行函数调用的时候优先级顺序为:非模板函数、模板特例化函数、模板函数
五、函数模板的作用域:
只在本文件