c++:模板(template)
目录
非类型模板参数(non-type template parameter)
C++ 为什么需要模板?
想象你写了一个函数,求两个数中较大的一个:
int max(int a, int b) {
return a > b ? a : b;
}
然后你想比较 double 呢?只能再写一遍:
double max(double a, double b) {
return a > b ? a : b;
}
再来个 float、long、char 呢?
写来写去,逻辑都一样,只是类型不同,代码重复、繁琐、难维护。
💡 那我们就该问一个第一性问题:
为什么我们不能写一段“通用的逻辑”,让编译器自动帮我们“适配不同类型”呢?
这时候,C++ 说:你可以,用模板(template)!
模板的本质:写一次逻辑,自动适配类型
模板 = “参数化的类型”
就像函数可以传参数,模板可以传“类型”做参数!
1. 函数模板
template<typename T>
T max(T a, T b) {
return a > b ? a : b;
}
-
template<typename T>:声明一个类型参数T -
T就是一个“占位符类型”,在使用的时候再决定具体是int、double等 -
函数逻辑只写一次,但可以用很多种类型
int a = 10, b = 20;
std::cout << max(a, b); // 自动推导为 int
double x = 5.5, y = 4.4;
std::cout << max(x, y); // 自动推导为 double
2. 类模板
让我们用模板类写一个简单容器:
template<typename T>
class Box {
public:
T value;
Box(T v) : value(v) {}
void print() {
std::cout << value << std::endl;
}
};
编译器在看到 Box<int> 时,会生成一个完整的 Box<int> 版本的类。
Box<int> b1(42); // 用 int 实例化
Box<std::string> b2("Hello");
b1.print(); // 输出 42
b2.print(); // 输出 Hello
3. 多个模板参数
template<typename T, typename U>
void printPair(T a, U b) {
std::cout << a << ", " << b << std::endl;
}
非类型模板参数(non-type template parameter)
为什么需要 template<int N>?
想象你要写一个容器类,比如一个定长数组:
class MyArray {
int data[10]; // 长度固定为 10
};
问题是:
-
这个
10是写死的; -
如果你想要长度为 20 的,就要再写一个类;
-
想写一个可以支持「不同大小」的类,怎么办?
你可能会说:用构造函数传一个大小进去:
class MyArray {
int* data;
int size;
public:
MyArray(int sz) : size(sz) {
data = new int[size];
}
};
这当然是可行的,但有两个问题:
-
内部用的是
new,需要自己管理内存; -
数组大小不是编译期确定的,比如你不能写
int arr[size];
所以我们思考一个第一性问题:
能不能像模板那样,把「数组大小」也当成一个参数,在编译时就固定下来?
当然可以!用 非类型模板参数(non-type template parameter)!
什么是非类型模板参数?
你熟的写法是这样:
template<typename T>
这是类型模板参数 —— 类型是参数。
template<int N>
这是非类型模板参数 —— 参数是值(这里是整型值)。
示例:用模板参数创建固定大小的数组
template<typename T, int N>
class MyArray {
private:
T data[N]; // 👈 数组大小由模板参数 N 决定
public:
T& operator[](int index) {
return data[index];
}
int size() const {
return N;
}
};
MyArray<int, 5> arr; // 创建一个大小为 5 的 int 数组
arr[0] = 10;
std::cout << arr.size(); // 输出 5
这段代码的核心点:
-
N是一个整型常量(在编译期就知道) -
T data[N];的数组大小是固定的、静态分配的 -
不需要手动
new和delete,效率更高,管理更安全
⚠️ 模板的使用注意
-
模板函数不能自动类型转换(
int+double会报错):
max(1, 2.0); // ❌ 类型不一致
2. 模板是编译期展开的,编译器会为每种用到的类型生成一份代码,所以模板用得多,会导致编译文件体积变大(这叫“代码膨胀”)。
3. 模板实现和声明最好写在同一个头文件中,不然链接时可能找不到定义。
最后用一句话总结:
C++ 模板就是“用类型做参数”的工具,让你写出能适应各种类型的通用代码,是 C++ 泛型编程的基石。
更多推荐
所有评论(0)