C++ 從基礎到精通 — 第 13 講
使用模板減少不同類型的重複程式碼
該部落格上撰寫的文章是出於教學目的而創建的。 另外,文章中的資訊可能不正確,請謹慎。
有時,尋找物品 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 中,則可能會因找不到特定類型的程式碼而出現連結錯誤。
使用模板的標準
如果程式碼類型不同但含義相同,則模板可以減少重複。 相反,如果將具有不同操作和職責的程式碼強制放入單一範本中,則條件語句和特殊處理就會增加。
模板並不是泛化所有程式碼的函數。 最好將其視為一種工具,可以安全地將相同的規則應用於多種類型,並防止在編譯階段出現錯誤的組合。