目录

C++ 为什么需要模板?

模板的本质:写一次逻辑,自动适配类型

1. 函数模板

2. 类模板

3. 多个模板参数

非类型模板参数(non-type template parameter) 

为什么需要 template ?

什么是非类型模板参数?

示例:用模板参数创建固定大小的数组 

⚠️ 模板的使用注意

最后用一句话总结: 

C++ 为什么需要模板?

想象你写了一个函数,求两个数中较大的一个: 

int max(int a, int b) {
    return a > b ? a : b;
}

 然后你想比较 double 呢?只能再写一遍:

double max(double a, double b) {
    return a > b ? a : b;
}

 再来个 floatlongchar 呢?

写来写去,逻辑都一样,只是类型不同,代码重复、繁琐、难维护。 

💡 那我们就该问一个第一性问题: 

为什么我们不能写一段“通用的逻辑”,让编译器自动帮我们“适配不同类型”呢? 

这时候,C++ 说:你可以,用模板(template)!

模板的本质:写一次逻辑,自动适配类型

模板 = “参数化的类型”
就像函数可以传参数,模板可以传“类型”做参数!


1. 函数模板

template<typename T>
T max(T a, T b) {
    return a > b ? a : b;
}
  • template<typename T>:声明一个类型参数 T

  • T 就是一个“占位符类型”,在使用的时候再决定具体是 intdouble

  • 函数逻辑只写一次,但可以用很多种类型

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];
    }
};

这当然是可行的,但有两个问题:

  1. 内部用的是 new,需要自己管理内存;

  2. 数组大小不是编译期确定的,比如你不能写 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]; 的数组大小是固定的、静态分配的

  • 不需要手动 newdelete,效率更高,管理更安全

 


⚠️ 模板的使用注意

  1. 模板函数不能自动类型转换(int + double 会报错):

max(1, 2.0); // ❌ 类型不一致

 2. 模板是编译期展开的,编译器会为每种用到的类型生成一份代码,所以模板用得多,会导致编译文件体积变大(这叫“代码膨胀”)。

3. 模板实现和声明最好写在同一个头文件中,不然链接时可能找不到定义。 

最后用一句话总结: 

C++ 模板就是“用类型做参数”的工具,让你写出能适应各种类型的通用代码,是 C++ 泛型编程的基石。 

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐