函数重载的应用,实现相同函数体、不同数据类型交换数值函数
//int型变量交换
void Swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
//float型变量交换
void Swap(float& a, float& b) {
int temp = a;
a = b;
b = temp;
}
//char型变量交换
void Swap(char& a, char& b) {
int temp = a;
a = b;
b = temp;
}
//bool型变量交换
void Swap(bool& a, bool& b) {
int temp = a;
a = b;
b = temp;
}
这些函数看起来有些许浪费空间,而函数模板可以将其压缩成一个函数。
我们知道,数据的值可以通过函数参数传递,在函数定义时数据的值是未知的,只有等到函数调用时接收了实参才能确定其值。这就是值的参数化。
在C++中,数据类型(如int、float等)也可以通过参数来传递,在函数定义时可以不声明具体的数据类型,转而通过参数来进行后续传递,实现类型的参数化。
而进行参数化数据类型传入的通用函数也就叫函数模板。我们试着将上面的代码修改一下。
#include <iostream>
using namespace std;
template<typename T> void Swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
int n1 = 10, n2 = 20;
float f1 = 11.1, f2 = 22.2;
char c1 = 'A', c2 = 'B';
bool b1 = false, b2 = true;
Swap(n1, n2);//int型变量交换
Swap(f1, f2);//float型变量交换
Swap(c1, c2);//char型变量交换
Swap(b1, b2);//bool型变量交换
return 0;
}
重点在于定义函数模板的关键字“template”,
<>
尖括号里的是类型参数(也就是虚拟的类型)。“typename”
是另外一个关键字,用来声明具体的类型参数,这里的类型参数就是T
。从整体上看,template<typename T>
被称为模板头。
类型参数的命名规则和字符的命名规则是一样的,命名T并不是特定的。
函数模板的总结语法:
template <typename 类型参数1 , typename 类型参数2 , ...> 返回值类型 函数名(形参列表){
//在函数体中使用类型参数,如命名为T,则数据的建立类型都是T
}
而类型参数在一个通用函数中可以建立多个,并以逗号“,”隔开,如果我们需要导入的形参中存在两个数据类型的参数,则需要定义两个类型参数,以此类推至3、4....个不等。
其实,“tempname”也可以用"class"来替代,如:
template<class T> void Swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
除了将"tempname"换成"class"其他没有变化,效果是一样的。
而我们的通用函数也可以进行提前声明,如声明其他函数一样
#include <iostream>
using namespace std;
template<class T> void Swap(T& a, T& b);
int main() {
int num1 = 10, num2 = 20;
float num3 = 11.1, num4 = 22.2;
char num5 = 'A', num6 = 'B';
bool num7 = false, num8 = true;
Swap(num1, num2);//int型变量交换
Swap(num3, num4);//float型变量交换
Swap(num5, num6);//char型变量交换
Swap(num7, num8);//bool型变量交换
return 0;
}
template<class T> void Swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}