C++泛型编程
一、泛型编程基础
1. 核心概念
- 实现算法与数据结构的分离
- 基于模板技术(函数模板/类模板)
- 本质:类型参数化,减少重复代码
- 典型应用:STL容器、迭代器、算法
2. 类型本质
- 内存布局的抽象
- 不同类型对应不同的内存分配策略
二、函数模板
1. 基本语法
cpp
template<typename T> // 或 template<class T>
返回类型 函数名(参数列表) {
// 函数体
}
2. 关键特性
- 支持隐式推导和显式指定类型
- 可重载(包括与普通函数重载)
- 可声明为inline/extern
- 严格类型匹配(不进行隐式转换)
3. 使用示例
cpp
template<class T>
T customMax(T a, T b) {
return a > b ? a : b;
}
// 使用
int main() {
cout << customMax(3, 5); // 隐式推导
cout << customMax<double>(3.1, 5); // 显式指定
}
4. 注意事项
- 避免与标准库函数名冲突(建议使用命名空间)
- 模板参数名在作用域内唯一
- 多参数模板需每个参数前加typename/class
cpp
template<typename T, class U> // 正确
void func(T a, U b);
三、类模板
1. 基本语法
cpp
template<class T1, typename T2>
class MyClass {
// 类成员
};
2. 对象创建
- 必须显式指定模板参数
cpp
MyClass<int, double> obj;
3. 成员函数外部定义
cpp
template<class T1, class T2>
返回类型 MyClass<T1,T2>::函数名(参数列表) {
// 函数体
}
4. 继承关系
cpp
// 继承具体化的模板类
class Derived : public Base<int> {...};
// 继承模板类
template<class T>
class Derived : public Base<T> {...};
四、模板高级特性
1. 默认模板参数(仅类模板)
cpp
template<class T = int>
class Container {...};
2. 模板编译机制
- 两次编译原则:
- 模板定义时检查语法
- 实例化时检查类型相关操作
3. 代码组织要求
- 模板定义必须放在头文件中
- 避免分离式编译问题
五、最佳实践
- 命名规范
- 模板参数使用大写字母(如T, U)
- 模板类/函数添加
_t
后缀(可选)
- 类型安全
- 使用static_assert进行类型约束
cpp
template<class T>
class Vector {
static_assert(std::is_arithmetic<T>::value,
"Numeric type required");
};
- 性能优化
- 对常用类型进行显式实例化
cpp
template class Vector<int>; // 显式实例化
六、常见问题
- 链接错误
- 确保模板定义在头文件中
- 类型推导失败
- 混合类型参数时需显式指定
cpp
add(3, 4.5); // 错误
add<double>(3, 4.5); // 正确
- 代码膨胀
- 使用公共基类减少实例化次数
附:核心差异对比表
特性 | 函数模板 | 类模板 |
---|---|---|
类型推导 | 支持隐式推导 | 必须显式指定 |
默认参数 | 不支持 | 支持 |
继承 | 不可继承 | 可继承 |
静态成员 | 每个实例化有独立静态成员 | 同左 |
虚函数 | 不能声明虚函数 | 成员函数可为虚函数 |