博客 / 詳情

返回

每日一個C++知識點|模板

什麼是模板

C++ 是一門多範式的編程語言,除了面向對象的特點之外,還具備泛型編程的特點,其中模板是泛型編程的核心工具

模板是一份與類型無關的通用代碼,編譯器會根據你傳入的類型,自動推導和生成對應類型的具體代碼,這個過程叫 “模板實例化”,其中模板包括函數模板類模板

函數模板

如果不使用函數模板,實現兩個值交換的函數,會根據傳入參數的數據類型不同會有以下幾種情況:

#include <iostream>
#include <string>  
using namespace std; 

void Swap(int &a, int &b) // 交換兩個int型變量的值。
{
    int tmp = a;
    a = b;  
    b = tmp; 
}

void Swap(double& a, double& b) // 交換兩個double型變量的值。
{
    double tmp = a;
    a = b; 
    b = tmp; 
}

void Swap(string& a, string& b) // 交換兩個string型變量的值。
{
    string tmp = a;
    a = b; 
    b = tmp; 
}

由上述代碼所示,對每一種數據類型的交換,明明是函數邏輯相同,但都要重複寫一遍,這種代碼方式明顯是不高效的,如果用函數模板的方法應該怎麼寫呢?下面讓我們來了解以下函數模板

函數模板是用於實現通用函數,避免因為參數數據類型不同而重複寫相同邏輯的代碼

基礎語法

函數模板的基本使用方法如下

template <typename T>  
返回值類型 函數名(參數列表) {
    // 函數邏輯(用T表示任意類型)
}

其中template是模板關鍵字,用於聲明接下來的代碼是一個模板,typename是類型參數的聲明符,用於聲明後面的標識符是一個 “類型參數”,T是你自定義的類型參數名,是一個 “類型佔位符”,代表任意數據類型

下面我們用參數模板的方法來簡化上述交換函數的代碼

template <typename T>  
void Swap(T& a, T& b) { 
    T tmp = a; 
    a = b;
    b = tmp;
}

使用函數模板,短短几行代碼,就可以實現上述三個不同數據類型的參數的交換函數,這就是使用模板函數帶來的價值

多個類型參數的情況

上述是單個類型的參數的情況,交換的都是兩個相同類型的函數,如果要交換的是兩個不同類型的參數應該怎麼做呢?可以使用多個類型參數的情況的函數模板,下面用代碼進行舉例:

// 兩個類型參數:T1和T2
template <typename T1, typename T2>
void printPair(T1 a, T2 b) {
    cout << a << " " << b << endl;
}

// 使用時,T1=int,T2=string
printPair(10, "hello");
// T1=double,T2=bool
printPair(3.14, true);

通過以上代碼,我們也可以實現傳遞兩個不同類型參數的函數模板,總之,函數模板可以極大簡化我們的代碼,不需因為參數類型的不同而重複多寫函數邏輯相同的代碼,大大提高了代碼的複用

類模板

模板除了函數模板之外還有類模板,函數模板是通用函數,那麼類模板就是通用類,當你給類模板指定不同的數據類型時,編譯器會自動生成對應類型的具體類,這個過程就叫做類模板實例化。函數模板和類模板的區別就是函數模板可以自動推導類型,類模板必須顯式指定類型,下面是它的基礎用法:

// 模板參數聲明
template <class T> 
class 類模板名 {
private:
    // 成員變量可以使用類型參數T
    T m_data;
public:
    // 構造函數、成員函數的參數/返回值也可以使用T
    類模板名(T data) : m_data(data) {}
    T getData(); // 成員函數聲明
};

// 類模板的成員函數在類外定義時,需要重新聲明模板參數
template <class T>  // 第二處修改:typename → class
T 類模板名<T>::getData() {
    return m_data;
}

以上就是類模板的基礎用法,template類模板的聲明的關鍵字,class為模板類型參數聲明符,聲明後面的標識符T是一個類型參數,T是自定義的模板類型參數名,代表任意數據類型的"佔位符",下面用具體的代碼進行舉例説明:

#include <iostream>
#include <string>
using namespace std;

// 類模板:通用圖形類(T表示尺寸的數據類型,如int、double)
template <typename T>
class Shape {
private:
    string m_name;  // 圖形名稱(如"圓形"、"正方形")
    T m_size;       // 圖形的尺寸(T為類型參數:圓的半徑/正方形的邊長,類型可以是int/double)
public:
    // 構造函數:初始化圖形名稱和尺寸
    Shape(string name, T size) : m_name(name), m_size(size) {}

    // 成員函數:修改圖形的尺寸
    void setSize(T size) {
        m_size = size;
    }

    // 成員函數:獲取圖形的尺寸
    T getSize() {
        return m_size;
    }

    // 成員函數:顯示圖形的信息(簡單的輸出功能)
    void showInfo() {
        cout << "圖形:" << m_name << ",尺寸(半徑/邊長):" << m_size << endl;
    }
};

上述代碼中,用模板類型 T 表示圖形的尺寸數據類型

在代碼中函數模板和類模板其中一個顯著的區別是T函數模板中充當參數的類型,在類模板中充當類的成員變量和成員函數的類型,同時,類模板必須顯式指定類型,函數模板可自動推導類型,這是二者最直觀的區別

標準模板庫STL

STL 是C++標準庫的核心部分,它完全基於模板實現,為開發者提供了現成的、通用的容器、算法、迭代器等組件,是模板泛型編程的終極實戰成果,由於篇幅所限,這裏就不展開講,感興趣的話可以觀看往期的內容《每日一個C++知識點|STL基礎》,那裏有詳細説明

總結

  1. C++ 模板分為函數模板和類模板,核心是用類型參數T實現代碼的通用性,讓一份代碼適配不同類型
  2. 模板的關鍵是編譯期實例化:編譯器根據指定的具體類型,生成對應版本的函數或類
  3. 函數模板可自動推導類型,類模板必須顯式指定類型
  4. STL是完全基於模板實現的C++標準庫

本文到此結束,如果文章對你有用的話歡迎點贊收藏加關注哦~

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.