目录
C++模板初阶:泛型编程的强大工具
1. 泛型编程简介
在C++编程中,我们经常需要为不同类型实现相同功能的函数。例如,实现一个通用的交换函数:
void Swap(int& left, int& right) {
int temp = left;
left = right;
right = temp;
}
void Swap(double& left, double& right) {
double temp = left;
left = right;
right = temp;
}
void Swap(char& left, char& right) {
char temp = left;
left = right;
right = temp;
}
使用函数重载虽然可行,但存在明显缺点:
- 代码复用率低 - 每增加一个新类型就需要编写一个新函数
- 可维护性差 - 一个错误可能影响所有重载版本
泛型编程应运而生,它允许我们编写与类型无关的通用代码,是代码复用的一种重要手段。模板正是泛型编程的基础。
2. 函数模板
2.1 函数模板概念
函数模板代表了一个函数家族,它与类型无关,使用时根据实参类型产生特定的类型版本。
2.2 函数模板格式
template<typename T1, typename T2, ..., typename Tn>
返回值类型 函数名(参数列表) {}
例如,通用交换函数模板:
template<typename T>
void Swap(T& left, T& right) {
T temp = left;
left = right;
right = temp;
}
注意:
typename是定义模板参数的关键字- 也可以用
class代替typename(但不能用struct)
2.3 函数模板原理
函数模板本身不是函数,而是编译器生成具体函数的模具。编译器在编译阶段根据传入的实参类型推演模板参数,生成对应的函数代码。
例如,当使用double类型调用Swap时,编译器会生成专门处理double的代码;对于char类型也是如此。
2.4 函数模板实例化
使用不同类型的参数调用函数模板称为实例化,分为两种方式:
隐式实例化
让编译器根据实参自动推演模板参数类型:
template<class T>
T Add(const T& left, const T& right) {
return left + right;
}
int main() {
int a1 = 10, a2 = 20;
double d1 = 10.0, d2 = 20.0;
Add(a1, a2); // T被推演为int
Add(d1, d2); // T被推演为double
// Add(a1, d1); // 错误:无法确定T应为int还是double
Add(a1, (int)d1); // 解决方案1:强制类型转换
return 0;
}
显式实例化
在函数名后的<>中指定模板参数的实际类型:
int main() {
int a = 10;
double b = 20.0;
Add<int>(a, b); // 显式指定T为int
return 0;
}
如果类型不匹配,编译器会尝试隐式转换,失败则报错。
2.5 模板参数匹配原则
- 非模板函数优先:当非模板函数和同名函数模板都匹配时,优先调用非模板函数
// 专门处理int的加法函数
int Add(int left, int right) {
return left + right;
}
// 通用加法函数模板
template<class T>
T Add(T left, T right) {
return left + right;
}
void Test() {
Add(1, 2); // 调用非模板函数
Add<int>(1, 2); // 调用模板生成的版本
}
-
更优匹配原则:如果模板能产生更好匹配的函数,则选择模板版本
-
类型转换限制:模板函数不允许自动类型转换,而普通函数可以
3. 类模板
3.1 类模板定义格式
template<class T1, class T2, ..., class Tn>
class 类模板名 {
// 类内成员定义
};
示例:栈类模板
#include <iostream>
using namespace std;
template<typename T>
class Stack {
public:
Stack(size_t capacity = 4) {
_array = new T[capacity];
_capacity = capacity;
_size = 0;
}
void Push(const T& data);
private:
T* _array;
size_t _capacity;
size_t _size;
};
// 类模板成员函数定义
template<class T>
void Stack<T>::Push(const T& data) {
// 实现代码
}
注意:模板的声明和定义通常放在同一个文件中,分离到.h和.cpp文件可能导致链接错误。
3.2 类模板实例化
类模板实例化与函数模板不同,必须在类模板名后跟<>并指定具体类型:
Stack<int> intStack; // 实例化为int类型的栈
Stack<double> dblStack; // 实例化为double类型的栈
类模板名本身不是真正的类,实例化后的结果才是真正的类类型。
总结
C++模板是泛型编程的核心工具,它能够:
- 提高代码复用率
- 增强代码可维护性
- 保持类型安全
掌握函数模板和类模板的使用是成为高级C++程序员的重要一步。在实际开发中,合理使用模板可以大幅减少重复代码,提高开发效率。
C++模板初阶:泛型编程利器
4219

被折叠的 条评论
为什么被折叠?



