首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 泛型編程基礎:模板通識與函數/類模板實戰

     編輯:關於C++

從一個「通用加法函數」出發,理解為什麼 C++ 需要模板、什麼是泛型編程。本文涵蓋函數模板、類模板、實例化機制、實參推演、特化、重載規則等核心知識點,配合編譯器輸出圖解,打牢泛型編程根基。

為什麼需要模板?

早期嘗試:

  • 函數重載:類型一多就要寫 N 個版本,維護災難;返回類型不同無法重載。
  • 公共基類:失去類型檢查,強制繼承耦合度高。
  • 宏:無類型檢查,預處理階段替換,調試困難。

泛型編程 = 編寫與類型無關的代碼,以不變的代碼框架承載可變的類型。模板是其 C++ 實現基石。

函數模板

語法格式

template <typename T> // 或 class T
返回類型 函數名(參數列表) { ... }

基本示例

template <typename T>
T Add(T left, T right) { return left + right; }

int main() {
    Add(1, 2);        // OK,推演 T=int
    Add(1, 2.0);      // Error:兩個實參類型不同,無法確定單一 T
}

編譯錯誤示例

實例化與兩次編譯

  1. 定義期檢查:語法錯誤(如漏分號)。
  2. 實例化期檢查:實際類型是否支援所有操作(如 operator+)。

實參推演規則

  • 多模板參數必須完全匹配:fun(1, 'a', 3.14) → fun<int, char, double>
  • 推演結果

類型轉換限制

編譯器不會隱式轉換實參以匹配已有實例化,而是產生新實例:

template<typename T> T Add(T a, T b);
int Add(int a, int b); // 非模板版本
Add(1.2, 3.4); // 生成 Add<double>,而非轉 int 調用非模板版

生成double版本

僅允許兩種轉換:

  1. const 轉換(非 const → const 引用/指針)
  2. 數組/函數 → 指針退化

模板參數分類

  • 類型參數:typename T / class T
  • 非類型參數:編譯期常量(整型、指針、引用)
    例:template<typename T, int Size> void sum(T (&arr)[Size])

命名規則:同一參數列表中不可重名;遵循作用域遮蔽規則。

命名遮蔽

重名錯誤

缺少typename錯誤

函數模板重載規則

int Max(int a, int b);                    // 非模板
template<typename T> T Max(T a, T b);     // 模板1
template<typename T> T Max(T a, T b, T c); // 模板2

Max(10, 20);           // 調用非模板(優先)
Max<>(10, 20);        // 強制調用模板1
Max(10, 20.12);        // 調用模板1(double 更好匹配)
Max<int>(10.0, 20.0); // 顯式指定 T=int

核心原則:非模板優先;模板不隱式轉換;Max<> 強制只考慮模板。

模板特化

為特定類型提供定制實現:

template<typename T> int cmp(const T& a, const T& b) { return a - b; }
template<> int cmp<const char*>(const char*& a, const char*& b) {
    return strcmp(a, b); // 字符串比較特化
}

要求:實參類型必須與特化版形參完全匹配(含 const/引用)。

類模板

語法與實例化

template<typename T> class SeqList {
    int _size, _capacity; T* _data;
public:
    SeqList() : _size(0), _capacity(10), _data(new T[_capacity]) {}
    ~SeqList() { delete[] _data; }
};

SeqList<int> sl1;      // 必須顯式指定 T=int
SeqList<double> sl2;  // 編譯器生成 SeqList<double> 完整類定義

不同於函數模板,類模板使用時必須顯式提供模板實參。

總結

特性函數模板類模板
實參推演自動(調用時)不支持(必須顯式)
特化函數模板特化類模板特化/偏特化
預設參數不支持支持(template<typename T=int>)
編譯模型包含模型(頭文件含定義)包含模型

模板是 C++ 泛型編程的基石,掌握其推演、實例化、特化規則,是寫出高效、安全、可復用庫代碼的前提。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved