497 字
1 分钟
【CPP】模板
泛型编程
- 面向对象:关注数据与类型的绑定(多态)。
- 泛型 / 模板:关注算法与数据结构,将类型参数化,编译期生成具体代码。
STL 即泛型编程的典型应用。
函数模板
template<typename T>T maximum(T a, T b) { return (a > b) ? a : b;}
int m = maximum(3, 5); // 推导 T = intdouble d = maximum<double>(3.1, 2.2); // 显式指定要点:
- 模板不是函数,是生成函数的“模具”;每个使用的
(T, 实参类型组合)会实例化一份函数。 - 定义通常在头文件中(或显式实例化在 .cpp),否则链接阶段找不到实例。
- 函数模板一般不支持与内置类型相同的隐式窄化转换规则(实参类型必须匹配或能推导)。
与普通函数共存
int add(int a, int b) { return a + b; }
template<typename T>T add(T a, T b) { return a + b; }
add(1, 2); // 优先非模板 add(int,int)add<>(1, 2); // 强制使用模板实例 add<int>add<double>(1, 2); // 显式模板重载与特化
- 多个模板或模板与非模板可构成重载集。
- 全特化:针对特定类型单独实现。
- 偏特化:仅类模板支持偏特化,函数模板只有全特化。
template<>const char* maximum<const char*>(const char* a, const char* b) { return strcmp(a, b) > 0 ? a : b;}局限性处理
对模板不适用的类型(如指针比较语义),可:
- 重载非模板函数;
- 模板特化;
- C++20 约束(
requires/ concepts)限制模板参数。
类模板
template<typename T>class Stack { std::vector<T> data;public: void push(const T& v) { data.push_back(v); } void pop() { if (!data.empty()) data.pop_back(); } T& top() { return data.back(); }};
Stack<int> s;Stack<std::string> ss;要点:
- 不能像函数模板那样自动推导类模板参数(C++17 起类模板参数推导 CTAD 有例外,如
pair p(1, 2.0);)。 - 成员函数若在类外实现,须带模板声明:
template<typename T>void Stack<T>::push(const T& v) { /* ... */ }类模板作函数参数
template<typename T>void process(Stack<T>& st) { /* ... */ }普通类继承类模板实例
template<typename T>class Vector { /* ... */ };
class MyVec : public Vector<int> {}; // 继承某一实例化类模板与友元、静态成员
每个 Stack<int>、Stack<double> 是不同类型,静态成员、友元各自独立。
编译模型(两次编译)
- 模板定义阶段:检查模板语法。
- 实例化阶段:根据调用生成具体函数/类,再编译。
因此错误可能在实例化时才暴露。
与 STL 的关系
容器 vector<T>、算法 sort、迭代器均为模板;详见 [CPP]STL.md。
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐
