C++ 讲解—函数模板
函数模板
1. 什么是函数模板?
如果你学过python,那么就可以简单的将函数模板理解为父类即可。如果你没有学过,c++是你的第一个计算机语言,那么我们可以想象一下刀具的打磨:你有套刀具胚子,想要生产出用于切割不同材质的物品的刀具,比如水果、肉类、纸张等。这里的“刀具胚子”就类似于一个函数模板。虽然不同材质的物品(数据类型)各异,但刀具的基本功能(函数的逻辑)是通用的。
水果刀:可以用来切水果(如苹果、香蕉)。打造成细长较厚的锋利刀子。
厨房刀:可以用来切肉类或蔬菜。打造成较大较厚的刀具。
裁纸刀:可以用来切纸张。打造成软薄且锋利刀具。
虽然具体的切割对象不同,但“切割”这个动作的本质是相同的。刀具的设计允许它适应不同的切割任务。
2. 为什么要用到函数模板?
在没有模板的情况下,如果我们想写一个函数来交换两个变量的值,可能需要为每种类型都写一个函数。函数模板可以解决这个问题。我们可以用一个函数模板处理不一样的数据类型。
3. 函数模板的实际应用案例
#include <iostream>
using namespace std;#定义函数模板--交换两个变量的值
template <typename T>
void swap(T& a, T& b) {T temp = a;a = b;b = temp;
}
#使用函数模板
int main() {int x = 5, y = 10;swap(x, y); // 自动生成 int 版本的 swap 函数double a = 3.14, b = 2.71;swap(a, b); // 自动生成 double 版本的 swap 函数return 0;
}
4. 在调用时,如何区别函数模板和普通函数?
当函数模板和同名(但不是模板)的函数同时存在时,需要分开调用。如下面这个例子:
#include <iostream>
using namespace std;// 普通函数(注意:为了验证程序的行为,返回较小值)
int maxof(int a, int b) { return a < b ? a : b; }// 函数模板
template <class Type> Type maxof(Type a, Type b) { return a > b ? a : b; }int main()
{int a, b;cout << "整数a:";cin >> a;cout << "整数b:";cin >> b;cout << "较大值为" << maxof(a, b) << "。\n";// 这里返回较小值cout << "较大值为" << maxof<int>(a, b) << "。\n";//这里返回较大值cout << "较大值为" << maxof<>(a, b) << "。\n";//这里返回较大值return 0;
}
在这里,我们命名普通函数和函数模板的时候都使用了maxof,那么在使用的时候如何将这两种形式区别开呢?我们可以使用maxof<int>(a,b)
和maxof<>(a,b)来调用模板函数。而常规的模式maxof(a,b)是用来调用普通函数的。
5. 使用显式特例化应对不同的数据类型
接着上面的例子,可以看到,整型数据可以用在比大小的常规函数和函数模板中。但是想要解决字符串比大小,就不知道如何下手了,那么我们可以使用显式特例化来解决问题。只需要在定义模板的时候,加入固定的参数类型即可:
#include <cstring>
#include <iostream>
using namespace std;// 求 a 和 b 中的较大值
template <class Type> Type maxof(Type a, Type b)
{return a > b ? a : b;
}// 求 a 和 b 中的较大值(const char* 型的特例化)
template <> const char* maxof<const char*>(const char* a, const char* b)
{return strcmp(a, b) > 0 ? a : b;
}int main()
{int a, b;char s[64], t[64];cout << "整数a:"; cin >> a;cout << "整数b:"; cin >> b;cout << "字符串s:"; cin >> s;cout << "字符串t:"; cin >> t;cout << "a和b中的较大值为" << maxof(a, b) << "。\n";cout << "s和t中的较大值为" << maxof<const char*>(s, t) << "。\n";cout << "s和\"ABC\"中的较大值为" << maxof<const char*>(s, "ABC") << "。\n";return 0;
}