Menu
CoddyTech

类模板

本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 65 课,共 104 课。

正如函数模板可以让你编写与类型无关的函数,类模板可以让你创建与类型无关的类。std::vector 这样的容器就是这样工作的:你只需定义一次结构,编译器就会为你使用的每种类型生成对应的版本。

template <typename T>
class Box {
    T value;
public:
    Box(T v) : value(v) {}
    T getValue() const { return value; }
    void setValue(T v) { value = v; }
};

int main() {
    Box<int> intBox(42);
    Box<std::string> strBox("Hello");
    
    std::cout << intBox.getValue() << std::endl;  // 42
    std::cout << strBox.getValue() << std::endl;  // Hello
}

与函数模板不同,使用尖括号从类模板创建对象时,你必须明确指定类型。然后,编译器会为该类型生成完整的类定义。

类模板可以有多个类型参数,甚至还可以有整数这样的非类型参数:

template <typename T, int Size>
class FixedArray {
    T data[Size];
public:
    T& operator[](int index) { return data[index]; }
    int size() const { return Size; }
};

FixedArray<double, 5> arr;  // 包含 5 个 double 值的数组
arr[0] = 3.14;

在类外定义成员函数时,你必须重复模板声明:

template <typename T>
class Container {
    T* data;
public:
    Container();
    ~Container();
};

template <typename T>
Container<T>::Container() : data(nullptr) {}

template <typename T>
Container<T>::~Container() { delete data; }

类模板是 C++ 泛型编程的基础,让你能够编写可用于任意类型的可复用数据结构。

challenge icon

挑战

简单

让我们使用类模板构建一个通用存储系统,创建一个可以存放任意数据类型的灵活容器。你会把模板类放在头文件中,并在主程序中使用不同类型来展示它的灵活性。

你需要创建两个文件:

  • Storage.h:定义一个名为 Storage 的类模板,作为一个简单容器来存放单个值,并提供一些实用操作:

    你的 Storage 模板应包含:

    • 一个用于存放值的私有成员
    • 一个接收初始值的构造函数
    • 一个返回所存放值的 getValue() 方法
    • 一个用于更新所存放值的 setValue() 方法
    • 一个 isEmpty() 方法:如果该值等于类型 T 的默认构造值,则返回 true;否则返回 false

    另外,创建一个名为 Pair 的类模板,它有两个类型参数,用于存放两个相关的值:

    • 用于存放第一个值和第二个值的私有成员,这两个值的类型可以不同
    • 一个用于初始化两个值的构造函数
    • 用于获取每个值的 getFirst() 和 getSecond() 方法
    • 一个用于打印 (<first>, <second>) 的 display() 方法
  • main.cpp:读取 4 个输入,每个输入占一行:
    1. 一个整数值
    2. 一个新的整数值
    3. 一个字符串值
    4. 一个 double 值

    通过以下操作展示你的模板:

    1. 使用第一个整数创建一个 Storage<int>,并打印:Int storage: <value>
    2. 使用 setValue() 将其更新为第二个整数,然后打印:Updated: <value>
    3. 使用输入的字符串创建一个 Storage<std::string>,并打印:String storage: <value>
    4. 检查字符串存储是否为空,并打印:Is empty: <true/false>(打印 true 或 false)
    5. 使用字符串值和 double 值创建一个 Pair<std::string, double>,然后调用 display()
    6. 使用两个整数输入创建一个 Pair<int, int>,然后调用 display()

例如,输入 42、100、Hello 和 3.14 时:

Int storage: 42
Updated: 100
String storage: Hello
Is empty: false
(Hello, 3.14)
(42, 100)

注意,同一个 Storage 模板可以轻松用于整数和字符串,而 Pair 可以组合不同类型的值。编译器会为你使用的每种类型组合生成单独的类定义。记得,单类型模板使用 template <typename T> 语法,包含多个类型参数的模板使用 template <typename T, typename U> 语法。

亲手试试

#include <iostream>
#include <string>
#include "Storage.h"

using namespace std;

int main() {
    // 读取输入
    int intValue1;
    int intValue2;
    string strValue;
    double doubleValue;
    
    cin >> intValue1;
    cin >> intValue2;
    cin >> strValue;
    cin >> doubleValue;
    
    // TODO: 用第一个整数创建 Storage<int>,输出:Int storage: <value>
    
    // TODO: 用 setValue() 将值更新为第二个整数,输出:Updated: <value>
    
    // TODO: 用输入的字符串创建 Storage<std::string>,输出:String storage: <value>
    
    // TODO: 检查字符串存储是否为空,输出:Is empty: true/false
    
    // TODO: 用字符串和 double 值创建 Pair<std::string, double>,调用 display()
    
    // TODO: 用两个整数创建 Pair<int, int>,调用 display()
    
    return 0;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器