泛型编程:写出类型无关的代码
想象一下,用同一个模具压制不同颜色的橡皮泥玩具——泛型编程就是这个思路。你写一份逻辑,编译器帮你生成处理各种数据类型的版本。
在 C 语言里,想交换两个变量的值,得针对 int、double、char 分别写几乎一样的函数:
void Swap(int& x, int& y) {
int tmp = x;
x = y;
y = tmp;
}
void Swap(double& x, double& y) {
double tmp = x;
x = y;
y = tmp;
}
void Swap(char& x, char& y) {
char tmp = x;
x = y;
y = tmp;
}
除了类型名,逻辑完全相同。C++ 的模板就是让你只写一次,让编译器去实例化出各个版本。
函数模板
1. 语法
函数模板代表一个函数家族,与具体类型无关。声明时用 template 关键字,尖括号里放类型参数:
template<typename T1, typename T2, ..., typename Tn>
void FunctionName(T1& a, T2& b) {
// ...
}
typename 可以换成 class,效果一样。
用模板改写上面的 Swap:
#include <iostream>
using namespace std;
template<typename T>
void Swap(T& x, T& y) {
T tmp = x;
x = y;
y = tmp;
}
int main() {
int a = 1, b = 2;
cout << "交换前:a:" << a << " b:" << b << endl;
Swap(a, b); // 编译器推导 T 为 int
cout << "交换后:a:" << a << " b:" << b << endl;
double c = 1.2, d = 23.1;
cout << "交换前:c:" << c << " d:" << d << endl;
Swap(c, d); // 编译器推导 T 为 double
cout << "交换后:c:" << c << " d:" << d << endl;
return 0;
}
模板本身不是可执行代码,更像一张蓝图。编译器看到 Swap(a, b),推断 T 是 int,就生成一份处理 int 的函数;看到 Swap(c, d),再生成一份 double 版本。
2. 实例化:隐式与显式
用不同参数调用模板的过程叫实例化。最常见的是隐式实例化——你只需调用,编译器自动推导类型。
但碰上混用类型的情况,编译器就懵了:
#include <iostream>
using namespace std;
template<class T>
T Add(const T& x, const T& y) {
return x + y;
}
int main() {
int a = 1;
double b = 2.2;
Add(a, b); // 错误:T 该是 int 还是 double?
return 0;
}
解决办法有三种:
- 强制类型转换:
Add(a, (int)b); - 多用模板参数:
template<class T1, class T2> T1 Add(const T1& x, const T2& y); - 显式实例化:直接在调用时指定
T。
显式实例化就是给函数名后加尖括号:
Add<int>(a, b); // T 明确为 int,b 被隐式转换为 int
类模板更常用显式实例化,但函数模板在推导失败时也少不了这一招。
类模板
类模板只是在类名前加上模板声明:
template<class T1, class T2, ..., class Tn>
class ClassName {
// 成员
};
例如,一个简易栈:
#include <iostream>
using namespace std;
template<typename T>
class Stack {
public:
Stack(size_t capacity = 4) {
_array = new T[capacity];
_capacity = capacity;
_size = 0;
}
private:
T* _array;
size_t _capacity;
size_t _size;
};
类型用 T 占位,之后可以实例化成 int 栈、double 栈……比 typedef 灵活得多。
与函数模板不同,类模板实例化不能靠隐式推导,因为没有参数可猜类型,必须显式写出:
Stack<int> st1; // 存储 int 的栈
Stack<double> st2; // 存储 double 的栈
这种显式指定正是类模板的常规用法。

