← 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 中,則可能會因找不到特定類型的程式碼而出現連結錯誤。

使用模板的標準

如果程式碼類型不同但含義相同,則模板可以減少重複。 相反,如果將具有不同操作和職責的程式碼強制放入單一範本中,則條件語句和特殊處理就會增加。

模板並不是泛化所有程式碼的函數。 最好將其視為一種工具,可以安全地將相同的規則應用於多種類型,並防止在編譯階段出現錯誤的組合。