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++ 实现了泛型编程,显著提升了代码的可维护性和复用性。