← SEARCHABLE ARCHIVE
C / C++ · 2026-07-22

从 C++ 基础到掌握 — 第 13 集

使用模板减少不同类型的重复代码

INTERACTIVE READING MODE →

该博客上撰写的文章是出于教学目的而创建的。 另外,文章中的信息可能不正确,请谨慎。

有时,查找物品 ID 的函数和查找怪物 ID 的函数具有几乎相同的形状。 如果只是数据类型不同而行为相同,则可以使用模板创建通用规则,而不是复制代码。

函数模板

让我们首先创建一个返回两个值中较大者的函数。

template <typename T>
T Max(const T& a, const T& b)
{
    return a < b ? b : a;
}

int highLevel = Max(10, 20);
float highDamage = Max(12.5f, 8.0f);

T是调用函数时改变实际类型的地方。 编译器Max<int>和Max<float>根据需要创建每个函数。

但Max(10, 3.5f)如果传递不同的类型,编译会失败,因为无法确定一个T。 您必须显式匹配分别接受这两种类型的类型或设计模板。

类模板

如果你想对多种类型使用相同大小的槽,你也可以创建一个类作为模板。

template <typename T, std::size_t Size>
class Inventory
{
public:
    T& At(std::size_t index)
    {
        return slots.at(index);
    }

    const T& At(std::size_t index) const
    {
        return slots.at(index);
    }

private:
    std::array<T, Size> slots{};
};

Inventory<Item, 20> itemInventory;
Inventory<Skill, 8> skillInventory;

T 是类型,Size 是编译时确定的值。 std::array由于大小在运行时不会改变,因此有利于表达固定槽。

模板和头文件

常规函数可以在标头中声明并在 cpp 中定义。 但是,模板的定义在编译器为实际类型创建代码时必须可见。

// Inventory.h
template <typename T>
class Inventory
{
public:
    void Add(const T& value)
    {
        values.push_back(value);
    }

private:
    std::vector<T> values;
};

所以模板定义通常写在头部。 如果只将声明放在 header 中,而将定义隐藏在 cpp 中,则可能会因找不到特定类型的代码而出现链接错误。

使用模板的标准

如果代码类型不同但含义相同,则模板可以减少重复。 相反,如果将具有不同操作和职责的代码强制放入单个模板中,则条件语句和特殊处理就会增加。

模板并不是泛化所有代码的函数。 最好将其视为一种工具,可以安全地将相同的规则应用于多种类型,并防止在编译阶段出现错误的组合。