497 字
1 分钟
【CPP】模板
2026-03-27

泛型编程#

  • 面向对象:关注数据与类型的绑定(多态)。
  • 泛型 / 模板:关注算法与数据结构,将类型参数化,编译期生成具体代码。

STL 即泛型编程的典型应用。

函数模板#

template<typename T>
T maximum(T a, T b) {
return (a > b) ? a : b;
}
int m = maximum(3, 5); // 推导 T = int
double 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;
}

局限性处理#

对模板不适用的类型(如指针比较语义),可:

  1. 重载非模板函数;
  2. 模板特化;
  3. 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>不同类型,静态成员、友元各自独立。

编译模型(两次编译)#

  1. 模板定义阶段:检查模板语法。
  2. 实例化阶段:根据调用生成具体函数/类,再编译。

因此错误可能在实例化时才暴露。

与 STL 的关系#

容器 vector<T>、算法 sort、迭代器均为模板;详见 [CPP]STL.md

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

【CPP】模板
https://lysj.work/posts/studynotes/cpp/cpp模板/
作者
Sekiro
发布于
2026-03-27
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录