1. 泛型编程
- 目标:编写与类型无关的通用代码,提高代码复用性。
- 问题:传统函数重载需为每种类型编写重复代码,维护成本高。
- 解决方案:使用模板(Template),通过编译器自动生成特定类型的代码。
2. 函数模板
定义:
template<typename T>
void Swap(T& left, T& right) {
T temp = left;
left = right;
right = temp;
}
- typename 或 class 声明模板类型参数。
原理:
- 编译器根据实参类型生成具体函数(如 Swap<int>、Swap<double>)。
- 模板是代码生成的 “模具”,避免手动编写重复代码。
实例化:
- 隐式实例化:编译器自动推导类型。
Swap(1, 2); // T 推导为 int
- 显式实例化:手动指定类型。
Swap<double>(3.14, 2.71); // 显式指定 T 为 double Swap(3, (doouble)2.71); //强转 double
- 匹配原则:
- 非模板函数与模板函数可共存,优先调用非模板函数。
- 模板函数不支持自动类型转换,普通函数支持。
3. 类模板
- 定义:
template<typename T> class Stack { public: Stack(size_t capacity = 4); void Push(const T& data); private: T* _array; size_t _capacity, _size; };
- 实例化:
Stack<int> st1; // 实例化为 int 类型的栈 Stack<double> st2; // 实例化为 double 类型的栈
- 注意事项:
- 类模板的声明和定义需放在同一文件中,否则可能导致链接错误。
- 成员函数在类外定义时需保留模板参数:
template<typename T> void Stack<T>::Push(const T& data) { _array[_size++] = data; }
4. 关键特性
- 类型安全:模板在编译期检查类型,避免运行时错误。
- 灵活性:支持动态指定类型,适应多种场景。
- 代码复用:一套模板代码适配所有类型,减少冗余。
5. 常见问题
- 类型推导冲突:当实参类型不一致时,需显式实例化或强制类型转换。
Add(1, 2.0); // 错误,类型不匹配 Add<double>(1, 2.0); // 正确,显式指定类型
- 分离编译问题:类模板的声明和定义不能分离到
.h
和.cpp
文件,否则链接失败。
6. 应用场景
- 容器类(如栈、队列)。
- 通用算法(如排序、查找)。
- 元编程(编译期计算,如
Factorial
模板)。
通过模板,C++ 实现了泛型编程,显著提升了代码的可维护性和复用性。