類模板是類的參數化定義,將類中可能變化的類型抽象為「虛擬類型參數」,編譯時根據實際類型參數實例化出具體類。實現了泛型編程,提高代碼復用性與類型安全性。
先寫一個針對特定類型(如 int)的完整類,確保邏輯正確。
將需變化的類型替換為虛擬類型名(如 numtype)。
template <typename numtype> // 或 template <class numtype>
class Compare {
public:
Compare(numtype a, numtype b) : x(a), y(b) {}
numtype max() { return (x > y) ? x : y; }
numtype min() { return (x < y) ? x : y; }
private:
numtype x, y;
};
Compare<int> cmp1(3, 7); // 具體化為 int 版本
Compare<float> cmp2(45.78, 93.6); // 具體化為 float 版本
Compare<char> cmp3('a', 'A'); // 具體化為 char 版本
關鍵點:Compare 是模板名,非具體類;numtype 是佔位符,僅在實例化時被實際類型替換。
template <typename numtype>
numtype Compare<numtype>::max() {
return (x > y) ? x : y;
}
注意:定義時需帶上模板參數列表,且類名後跟 <numtype>。
template <class T1, class T2>
class Pair {
T1 first; T2 second;
public:
Pair(T1 a, T2 b) : first(a), second(b) {}
};
Pair<int, double> p(10, 3.14);
類模板遵循普通類的作用域規則,僅在其可見範圍內可實例化對象。
模板定義通常放在頭文件中(或 .inl 包含),因為編譯器需在使用點看到完整定義以進行實例化。這也是「頭文件只有聲明」慣例的例外。
| 誤區 | 正確做法 |
|---|---|
| 嘗試在 .cpp 中分離模板定義與聲明 | 定義放在頭文件,或使用 explicit instantiation 顯式實例化常用類型 |
| 濫用模板導致代碼膨脹 | 將與類型無關的代碼提取到非模板基類或輔助函數 |
| 忽略模板參數約束 | C++20 使用 Concepts;C++17 用 static_assert/SFINAE 约束 |
類模板是 C++ 泛型編程的基石。掌握其定義、實例化機制、成員定義語法與編譯模型,能讓你編寫出類型安全、高復用、零開銷的泛型組件。