# 类模板

URL: https://caijiao.org/cpp/stl/templates-class
Source: docs/cpp/stl/templates-class.md
Description: 本节介绍 C++ 中的类模板，帮助理解如何定义通用类以及如何使用类模板进行类型参数化。

类模板是 C++ 中的一种泛型编程机制，它允许你定义一个与数据类型无关的类。类模板与函数模板类似，可以让你编写通用的代码来处理不同类型的对象。类模板可以让类的成员函数和数据成员类型更加灵活。

## 类模板的基本语法

类模板的定义与函数模板的定义类似，使用 `template` 关键字来定义类模板。类模板的基本格式如下：

```cpp
template <typename T>
class ClassName {
public:
    T value;
    
    ClassName(T val) : value(val) {}
    
    void display() {
        std::cout << value << std::endl;
    }
};
````

* `template <typename T>`：定义一个模板，`T` 代表类型参数。
* `ClassName`：类模板的名称。
* `T value`：类的成员变量类型是 `T`，可以是任意类型。
* `ClassName(T val)`：构造函数接受一个类型为 `T` 的参数，初始化 `value`。
* `display()`：成员函数输出 `value` 的值。

### 示例：类模板的使用

以下是一个简单的类模板示例，展示了如何定义和使用类模板：

```cpp
#include <iostream>
using namespace std;

template <typename T>
class Box {
public:
    T value;
    
    Box(T val) : value(val) {}
    
    void display() {
        cout << "Value: " << value << endl;
    }
};

int main() {
    Box<int> intBox(10);
    intBox.display();   // 输出 Value: 10

    Box<double> doubleBox(5.5);
    doubleBox.display();   // 输出 Value: 5.5

    return 0;
}
```

在上面的代码中，`Box` 是一个类模板，它可以处理不同类型的数据（如 `int` 和 `double`）。通过 `Box<int>` 和 `Box<double>` 创建了两个不同类型的对象，并分别调用 `display()` 成员函数输出 `value` 的值。

## 类模板的多个类型参数

类模板不仅支持单个类型参数，还可以接受多个类型参数，允许更复杂的数据结构。

### 示例：多个类型参数的类模板

```cpp
#include <iostream>
using namespace std;

template <typename T, typename U>
class Pair {
private:
    T first;
    U second;

public:
    Pair(T f, U s) : first(f), second(s) {}
    
    void display() {
        cout << "First: " << first << ", Second: " << second << endl;
    }
};

int main() {
    Pair<int, double> p1(3, 4.5);
    p1.display();  // 输出 First: 3, Second: 4.5

    return 0;
}
```

在此例中，`Pair` 类模板接收两个类型参数 `T` 和 `U`，并通过构造函数初始化两个成员变量。`display()` 函数将这两个成员变量打印出来。

## 类模板的成员函数

类模板的成员函数可以使用模板参数来定义，也可以在类模板外部进行定义。成员函数的定义与普通类相似，只是需要在函数定义前加上模板参数。

### 示例：类模板成员函数的定义

```cpp
#include <iostream>
using namespace std;

template <typename T>
class Calculator {
public:
    T add(T a, T b) {
        return a + b;
    }

    T subtract(T a, T b) {
        return a - b;
    }
};

int main() {
    Calculator<int> calcInt;
    cout << calcInt.add(5, 3) << endl;      // 输出 8
    cout << calcInt.subtract(5, 3) << endl; // 输出 2

    Calculator<double> calcDouble;
    cout << calcDouble.add(5.5, 3.3) << endl;   // 输出 8.8
    cout << calcDouble.subtract(5.5, 3.3) << endl;  // 输出 2.2

    return 0;
}
```

在这个示例中，`Calculator` 类模板定义了两个成员函数 `add` 和 `subtract`，分别执行加法和减法操作。我们在 `main()` 函数中分别实例化了 `int` 和 `double` 类型的 `Calculator` 对象，调用了类的成员函数。

## 模板特化

模板特化可以为特定类型提供不同的实现。与函数模板特化类似，类模板也可以特化为某一特定类型的实现。

### 示例：类模板特化

```cpp
#include <iostream>
using namespace std;

// 通用类模板
template <typename T>
class Printer {
public:
    void print(T value) {
        cout << "Generic print: " << value << endl;
    }
};

// 类模板特化：为 int 类型提供特化
template <>
class Printer<int> {
public:
    void print(int value) {
        cout << "Specialized print for int: " << value << endl;
    }
};

int main() {
    Printer<double> printDouble;
    printDouble.print(3.14);  // 输出 Generic print: 3.14

    Printer<int> printInt;
    printInt.print(10);  // 输出 Specialized print for int: 10

    return 0;
}
```

在此例中，`Printer` 类模板对 `int` 类型进行了特化，特化版本会输出不同的信息，而其他类型则使用通用版本。

## 默认模板参数

与函数模板一样，类模板也可以为模板参数提供默认值，调用时若未指定类型参数，将使用默认类型。

### 示例：默认模板参数

```cpp
#include <iostream>
using namespace std;

template <typename T = int>
class Box {
private:
    T value;
    
public:
    Box(T val) : value(val) {}
    
    void display() {
        cout << "Value: " << value << endl;
    }
};

int main() {
    Box<> box1(10);    // 使用默认类型 int
    box1.display();     // 输出 Value: 10

    Box<double> box2(3.14);
    box2.display();     // 输出 Value: 3.14

    return 0;
}
```

在此例中，`Box` 类模板使用 `T = int` 为默认模板参数，如果在实例化时未指定类型，编译器会自动使用 `int` 类型。

## 总结

类模板使得 C++ 类的设计更加灵活和可扩展。通过类模板，可以创建能够处理多种数据类型的类，避免代码重复。类模板支持多个类型参数、成员函数定义、模板特化以及默认模板参数等特性。

* **类模板**：通过 `template` 关键字定义，允许使用类型参数来定义类。
* **多个类型参数**：支持多个类型的模板参数。
* **模板特化**：为某些特定类型提供特化的实现。
* **默认模板参数**：为模板参数提供默认类型。

掌握类模板的使用，能够帮助开发人员写出更加灵活、通用的 C++ 类。
