函数模板
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 64 课,共 104 课。
想象一下,你编写了一个函数来找出两个整数中的最大值,随后发现还需要为双精度浮点数编写相同的逻辑,之后还要为字符串编写一次。如果没有模板,你就得为每种类型分别编写几乎相同的函数。函数模板可以解决这个问题:你只需编写一次逻辑,编译器就会自动生成适用于特定类型的版本。
函数模板使用 template 关键字,后面跟着尖括号中的模板参数:
template <typename T>
T maximum(T a, T b) {
return (a > b) ? a : b;
}
int main() {
std::cout << maximum(5, 3) << std::endl; // 使用 int 版本
std::cout << maximum(3.14, 2.71) << std::endl; // 使用 double 版本
std::cout << maximum('a', 'z') << std::endl; // 使用 char 版本
}编译器会检查每次调用,并为特定类型生成一个具体函数。这个过程称为模板实例化。需要时,你也可以显式指定类型:
std::cout << maximum<double>(5, 3.14) << std::endl; // 强制使用 double 版本模板可以有多个类型参数,从而实现更灵活的设计:
template <typename T, typename U>
void printPair(T first, U second) {
std::cout << first << ", " << second << std::endl;
}
printPair(42, "hello"); // T=int, U=const char*
printPair(3.14, 100); // T=double, U=int函数模板提供编译时多态,类型在编译代码时确定,而不是在运行时确定。这意味着与虚函数相比,运行时开销为零,因此模板非常适合对性能要求高的泛型代码。
挑战
简单让我们使用函数模板构建一个实用工具包,创建可与任何兼容类型配合使用的可复用操作。你会将通用函数组织在头文件中,并在主程序里展示它们的灵活性。
你将创建两个文件:
MathUtils.h:定义一组执行常见操作的函数模板:minimum:一个模板函数,接收两个类型相同的值,并返回较小的那个。clamp:一个模板函数,接收三个参数:一个值、下界和上界。它会返回限制在边界范围内的值(如果 value 小于 low,则返回 low;如果 value 大于 high,则返回 high;否则返回 value 本身)。swapValues:一个模板函数,接收两个类型相同的引用,并交换它们的值。main.cpp:读取 6 个输入(每个输入单独占一行):- 第一个整数
- 第二个整数
- 要进行范围限制的 double 值
- 下界(double)
- 上界(double)
- 一个字符
通过以下操作展示你的模板:
- 找出两个整数中的最小值并打印:
Min of <a> and <b>: <result> - 找出字符
'm'和你输入的字符中的最小值,并打印:Min of m and <char>: <result> - 对 double 值进行范围限制并打印:
Clamp <value> to [<low>, <high>]: <result> - 将第一个整数限制在范围 [0, 100] 内并打印:
Clamp <value> to [0, 100]: <result> - 交换两个整数并打印:
After swapValues: <a>, <b>
例如,输入 25、10、3.7、1.0、5.0 和 z 时:
Min of 25 and 10: 10
Min of m and z: m
Clamp 3.7 to [1, 5]: 3.7
Clamp 25 to [0, 100]: 25
After swapValues: 10, 25注意,每个模板函数都能轻松处理整数、double 和字符:编译器会为你使用的每种类型生成相应版本。你的 swapValues 函数应通过引用修改原始变量,展示模板也能像普通函数一样使用引用参数。
亲手试试
#include <iostream>
#include "MathUtils.h"
using namespace std;
int main() {
// 读取输入
int a, b;
double value, low, high;
char ch;
cin >> a;
cin >> b;
cin >> value;
cin >> low;
cin >> high;
cin >> ch;
// TODO: 用 minimum 模板求两个整数中的较小值
// 输出:"Min of <a> and <b>: <result>"
// TODO: 用 minimum 模板求 'm' 和输入字符中的较小值
// 输出:"Min of m and <char>: <result>"
// TODO: 对 double 值使用 clamp 模板
// 输出:"Clamp <value> to [<low>, <high>]: <result>"
// TODO: 对第一个整数使用 clamp 模板,范围为 [0, 100]
// 输出:"Clamp <value> to [0, 100]: <result>"
// TODO: 对两个整数使用 swapValues 模板
// 输出:"After swapValues: <a>, <b>"
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器