前言:这里仅介绍c++primer plus中的简单函数模板和模板重载
面向对象的继承和多态机制有效提高了程序的可重用性和可扩充性。在程序的可重用性方面,程序员还希望得到更多支持。举一个最简单的例子,为了交换两个整型变量的值,需要写下面的 Swap 函数:
void Swap(int & x, int & y)
{
int tmp = x;
x = y;
y = tmp;
}
为了交换两个 double 型变量的值,还需要编写下面的 Swap 函数:
void Swap (double & xr double & y)
{
double tmp = x;
x = y;
y = tmp;
}
如果还要交换两个 char 型变量的值,交换两个 CStudent 类对象的值……都需要再编写 Swap 函数。而这些 Swap 函数除了处理的数据类型不同外,形式上都是一样的。能否只写一遍 Swap 函数,就能用来交换各种类型的变量的值呢?继承和多态显然无法解决这个问题。因此,“模板”的概念就应运而生了。
众所周知,有了“模子”后,用“模子”来批量制造陶瓷、塑料、金属制品等就变得容易了。程序设计语言中的模板就是用来批量生成功能和形式都几乎相同的代码的。有了模板,编译器就能在需要的时候,根据模板自动生成程序的代码。从同一个模板自动生成的代码,形式几乎是一样的。
函数模板的原理
C++ 语言支持模板。有了模板,可以只写一个 Swap 模板,编译器会根据 Swap 模板自动生成多个 Sawp 函数,用以交换不同类型变量的值。
在 C++ 中,模板分为函数模板和类模板两种。函数模板是用于生成函数的,类模板则是用于生成类的。
函数模板的写法如下:
template <class 类型参数1, class类型参数2, ...>
返回值类型 模板名(形参表)
{
函数体
}
其中的 class 关键字也可以用 typename 关键字替换,例如:
template <typename 类型参数1, typename 类型参数2, ...>
函数模板看上去就像一个函数。前面提到的 Swap 模板的写法如下:
template <class T>
void Swap(T & x, T & y)
{
T tmp = x;
x = y;
y = tmp;
}
T 是类型参数,代表类型。编译器由模板自动生成函数时,会用具体的类型名对模板中所有的类型参数进行替换,其他部分则原封不动地保留。同一个类型参数只能替换为同一种类型。编译器在编译到调用函数模板的语句时,会根据实参的类型判断该如何替换模板中的类型参数。
例如下面的程序:
#include <iostream>
using namespace std;
template<class T>
void Swap(T & x, T & y)
{
T tmp = x;
x = y;
y = tmp;
}
int main()
{
int n = 1, m = 2;
Swap(n, m); //编译器自动生成 void Swap (int &, int &)函数
double f = 1.2, g = 2.3;
Swap(f, g); //编译器自动生成 void Swap (double &, double &)函数
return 0;
}
编译器在编译到Swap(n, m);时找不到函数 Swap 的定义,但是发现实参 n、m 都是 int 类型的,用 int 类型替换 Swap 模板中的 T 能得到下面的函数:
void Swap (int & x, int & y)
{
int tmp = x;
x = y;
y = tmp;
}
该函数可以匹配Swap(n, m);这条语句。于是编译器就自动用 int 替换 Swap 模板中的 T,生成上面的 Swap 函数,将该 Swap 函数的源代码加入程序中一起编译,并且将Swap(n, m);编译成对自动生成的 Swap 函数的调用。
同理,编译器在编译到Swap(f, g);时会用 double 替换 Swap 模板中的 T,自动生成以下 Swap 函数:
void Swap(double & x, double & y)
{
double tmp = x;
x = y;
y = tmp;
}
函数模板中可以有不止一个类型参数。例如,下面这个函数模板的写法是合法的: 、
template <class Tl, class T2>
T2 print(T1 argl, T2 arg2)
{
cout << arg1 << " " << arg2 << endl;
return arg2;
}
注意:在书写模板时,我们通常将函数模板写进头文件中,并且注意,函数声明和定义前均要加上 template <。。。。>这句话。 其实与我们之前写函数一样,只不过在声明和定义前加上了 template <>
模板的重载
函数模板本质上还是函数,所以他也有重载,即函数名相同,参数类型或者个数不同。
比如:
template<class T>
void Swap(T & x, T & y)
{
}
template<class T>
void Swap(T & x, T & y ,T &z)
{
}