什麼是模板
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基礎》,那裏有詳細説明
總結
- C++ 模板分為函數模板和類模板,核心是用類型參數T實現代碼的通用性,讓一份代碼適配不同類型
- 模板的關鍵是編譯期實例化:編譯器根據指定的具體類型,生成對應版本的函數或類
- 函數模板可自動推導類型,類模板必須顯式指定類型
- STL是完全基於模板實現的C++標準庫
本文到此結束,如果文章對你有用的話歡迎點贊收藏加關注哦~