- C++
C++ 函数模板学习笔记教程
- 2025-8-10 14:11:41 @
C++ 函数模板学习笔记教程
1. 什么是函数模板
函数模板(Function Template)是C++中的一种代码复用机制,它允许我们创建一个通用的函数定义,而不指定具体的数据类型。编译器会根据调用时提供的参数类型,自动生成相应类型的函数实例。
函数模板的主要优势:
- 代码复用:一份代码可以处理多种数据类型
- 类型安全:在编译时进行类型检查
- 灵活性:无需为每种数据类型编写重复代码
2. 函数模板的基本语法
函数模板的基本结构如下:
template <typename T> // 模板参数声明
返回类型 函数名(参数列表) {
// 函数体,可使用类型T
}
其中:
template
是关键字,表明这是一个模板<typename T>
是模板参数列表,T
是类型参数(也可以用class
代替typename
)T
可以在函数参数、返回值和函数体内作为类型使用
3. 第一个函数模板示例
下面是一个实现两个数相加的函数模板:
#include <iostream>
// 函数模板定义
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
// 自动推导类型为int
int int_sum = add(3, 5);
std::cout << "整数相加: " << int_sum << std::endl; // 输出 8
// 自动推导类型为double
double double_sum = add(2.5, 3.7);
std::cout << "浮点数相加: " << double_sum << std::endl; // 输出 6.2
// 显式指定类型
float float_sum = add<float>(1.2f, 3.4f);
std::cout << "浮点数相加: " << float_sum << std::endl; // 输出 4.6
return 0;
}
4. 函数模板的实例化
当我们调用函数模板时,编译器会根据传入的参数类型生成特定类型的函数,这个过程称为模板实例化。
实例化有两种方式:
-
隐式实例化:编译器根据传入的参数自动推断类型
int result = add(5, 10); // 隐式实例化为add<int>
-
显式实例化:手动指定模板参数类型
double result = add<double>(3.14, 2.71); // 显式指定为double类型
5. 多参数函数模板
函数模板可以有多个类型参数,用逗号分隔:
#include <iostream>
#include <string>
// 多参数函数模板
template <typename T1, typename T2>
void print_pair(T1 first, T2 second) {
std::cout << "Pair: " << first << ", " << second << std::endl;
}
int main() {
print_pair(10, 3.14); // T1=int, T2=double
print_pair("Hello", 42); // T1=const char*, T2=int
print_pair(std::string("Age"), 25); // T1=std::string, T2=int
return 0;
}
6. 函数模板的重载
函数模板可以像普通函数一样被重载,包括:
- 模板函数之间的重载
- 模板函数与普通函数的重载
#include <iostream>
// 基本模板:两个参数相加
template <typename T>
T add(T a, T b) {
std::cout << "使用模板 add(T, T): ";
return a + b;
}
// 重载模板:三个参数相加
template <typename T>
T add(T a, T b, T c) {
std::cout << "使用模板 add(T, T, T): ";
return a + b + c;
}
// 普通函数:处理字符串拼接
std::string add(const char* a, const char* b) {
std::cout << "使用普通函数 add(const char*, const char*): ";
return std::string(a) + std::string(b);
}
int main() {
std::cout << add(2, 3) << std::endl; // 使用两个参数的模板
std::cout << add(2, 3, 4) << std::endl; // 使用三个参数的模板
std::cout << add("Hello, ", "World!") << std::endl; // 使用普通函数
return 0;
}
注意:当普通函数和模板函数都能匹配时,编译器会优先选择普通函数。
7. 模板参数的默认值
C++11及以后的标准允许为模板参数指定默认值:
template <typename T = int> // 指定int为默认类型
T multiply(T a, T b) {
return a * b;
}
// 调用时可以不指定类型,使用默认的int
int result1 = multiply(3, 4); // 使用默认类型int
double result2 = multiply<double>(2.5, 4.0); // 指定为double
8. 非类型模板参数
除了类型参数,模板还可以有非类型参数,它们是编译时常量:
#include <iostream>
// 非类型模板参数示例:数组求和
template <typename T, int N>
T sum_array(T (&arr)[N]) {
T sum = 0;
for (int i = 0; i < N; ++i) {
sum += arr[i];
}
return sum;
}
int main() {
int int_arr[] = {1, 2, 3, 4, 5};
std::cout << "整数数组的和: " << sum_array(int_arr) << std::endl; // 15
double double_arr[] = {1.1, 2.2, 3.3};
std::cout << "浮点数数组的和: " << sum_array(double_arr) << std::endl; // 6.6
return 0;
}
9. 函数模板的特化
当需要为特定类型提供不同的实现时,可以使用模板特化:
#include <iostream>
#include <string>
// 通用模板
template <typename T>
T max_value(T a, T b) {
std::cout << "使用通用模板: ";
return (a > b) ? a : b;
}
// 对const char*类型的特化
template <>
const char* max_value<const char*>(const char* a, const char* b) {
std::cout << "使用const char*特化版本: ";
return (std::strcmp(a, b) > 0) ? a : b;
}
int main() {
std::cout << max_value(10, 20) << std::endl; // 使用通用模板
std::cout << max_value("apple", "banana") << std::endl; // 使用特化版本
return 0;
}
10. 函数模板的注意事项
-
模板定义通常放在头文件中:因为模板实例化需要看到完整的模板定义。
-
隐式类型转换受限:当使用模板时,参数的类型推导不进行隐式类型转换。
add(3, 5.5); // 错误!int和double类型不匹配 add<double>(3, 5.5); // 正确,显式指定类型
-
并非所有类型都适用:模板函数中的操作必须对所使用的类型有效。
// 这个模板不能用于不支持+运算符的类型 template <typename T> T add(T a, T b) { return a + b; }
-
编译错误可能难以理解:模板的错误信息通常比较复杂,需要仔细分析。
11. 总结
函数模板是C++中实现泛型编程的强大工具,它允许我们编写与类型无关的代码,提高代码复用性和灵活性。
掌握函数模板需要理解:
- 基本语法和使用方法
- 模板实例化机制
- 模板重载和特化
- 非类型模板参数的应用
通过合理使用函数模板,可以编写出更加通用、灵活且高效的C++代码。
0 条评论
目前还没有评论...