C++ 函數模板
- 2022 年 3 月 30 日
- 筆記
- Visual Studio for C++
•共勉
「那些瘋狂到以為自己能夠改變世界的人,才能真正改變世界。」
蘋果 「非同凡響」 廣告·1997
•函數模板
介紹
- C++另一種編程思想稱為 泛型編程 ,主要利用的技術就是模板
- C++提供兩種模板機制:函數模板 和 類模板
函數模板
語法格式
template <typename T>//聲明一個模板,告訴編譯器後面程式碼中緊跟著的 T 不要報錯,T 是一個通用數據類型 函數聲明或定義
- template:聲明創建模板
- typename:表面其後面的符號是一種數據類型
- T:通用的數據類型,名稱可以替換,通常為大寫字母
作用
建立一個通用函數,其函數返回值類型和形參類型可以不具體制定,用一個虛擬的類型來代表。
舉例說明
例如,對於如下交換函數:
void swapInt(int &a, int &b) { int tmp = a; a = b; b = tmp; }我們傳遞的參數只能是整數類型,如果我們想要交換 double 類型的呢?
那當然是重寫一份啦~
void swapDouble(double& a, double& b) { double tmp = a; a = b; b = tmp; }對於這兩份程式碼,你會發現除了參數類型不同外,交換的步驟都是相同的。
那如果要交換 short 類型的呢,在重寫一份嗎?
會不會過於啰嗦,下面就引出函數模板的強大之處。
我們可以這麼寫:
template <typename T>//聲明一個模板,告訴編譯器後面程式碼中緊跟著的T不要報錯,T是一個通用數據類型 void mySwap(T& a, T& b) { T tmp = a; a = b; b = tmp; }利用函數模板實現數據交換,有兩種調用方式:
- 自動類型推導
- 顯示指定類型
void test() { int a = 10; int b = 20; mySwap(a, b);//1.自動類型推到 cout << "a = " << a << endl; cout << "b = " << b << endl; double c = 30; double d = 40; mySwap<double>(c, d);//2.顯示指定類型 cout << "c = " << c << endl; cout << "d = " << d << endl; }對於方式 1,編譯器會自動識別傳遞的參數類型,並做相應的調整:
注意事項 1
傳遞的參數類型必須是同種類型的,即必須推導出一致的數據類型 T 才可以使用。
比如就不能通過 mySwap 函數交換 int 和 double 類型的數據:
void test() { int a = 10; double b = 20; myswap(a, b); }由於 a,b 不是同種類型的,在編譯階段就會報錯:
提示推導不出一致的 T 類型。
注意事項 2
必須遵循模板的聲明和函數的聲明一對一使用,即模板的聲明只作用於緊挨著的函數聲明。
比如下面這種程式碼就會報錯:
template <typename T> void func1(T &a){} void func2(T &a){}
因為聲明的函數模板 T 只對 func1 起作用,如果 func2 也想用,必須重新聲明:
template <typename T> void func1(T &a) {} template <typename T> void func2(T &a) {}注意事項 3
模板必須要確定出 T 的數據類型,才可以使用。
比如如下程式碼就會報錯:
template <typename T> void func() {} void test() { func(); }因為函數 func() 的聲明緊挨著模板的聲明,所以他倆就是一對一的關係,那麼要想調用 func ,就必須給出 T 的數據類型;
不然編譯階段都不通過。
對於這種不含參數的函數模板,必須使用 顯示指定類型 來調用:
template <typename T> void func() {} void test() { func<int>(); }其中 <int> 隨便寫個數據類型就行,作用就是告訴函數模板傳遞的 T 為 XX 類型 。
•學以致用
有了函數模板的知識儲備,下面來寫一個排序函數,不管是傳入 int 類型 還是 char 類型 都可以實現升序排列。
選擇排序
template <typename T> void mySwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } template <typename T> void mySort(T arr[],int first,int last)//order [first, last) { for (int i = first; i < last; i++)//選擇排序 { int minIndex = i; for (int j = i + 1; j < last; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } mySwap(arr[i], arr[minIndex]); } }調用該排序函數
template <typename T> void print(const T arr[], int first, int last)//輸出數組[first, last) { for (int i = first; i < last; i++) cout << arr[i] << " "; cout << endl; } void test1() { //測試對整形數組進行排序 int arr[10]; for (int i = 0; i < 10; i++) arr[i] = rand()%20;//隨機產生[0~20)之間的隨機數 cout << "排序前:"; print(arr, 0, 10); mySort(arr, 0, 10); cout << "排序後:"; print(arr, 0, 10); } void test2() { //測試對字元型數組進行排序 char arr[10]; for (int i = 0; i < 10; i++) arr[i] = 'A'+rand() % 20;//隨機產生[0~20)之間的隨機數 cout << "排序前:"; print(arr, 0, 10); mySort(arr, 0, 10); cout << "排序後:"; print(arr, 0, 10); }CODE
#include<bits/stdc++.h> using namespace std; template <typename T> void mySwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } template <typename T> void mySort(T arr[],int first,int last)//order [first, last) { for (int i = first; i < last; i++)//選擇排序 { int minIndex = i; for (int j = i + 1; j < last; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } mySwap(arr[i], arr[minIndex]); } } template <typename T> void print(const T arr[], int first, int last)//輸出數組[first, last) { for (int i = first; i < last; i++) cout << arr[i] << " "; cout << endl; } void test1() { //測試對整形數組進行排序 int arr[10]; for (int i = 0; i < 10; i++) arr[i] = rand()%20;//隨機產生[0~20)之間的隨機數 cout << "排序前:"; print(arr, 0, 10); mySort(arr, 0, 10); cout << "排序後:"; print(arr, 0, 10); } void test2() { //測試對字元型數組進行排序 char arr[10]; for (int i = 0; i < 10; i++) arr[i] = 'A'+rand() % 20;//隨機產生[0~20)之間的隨機數 cout << "排序前:"; print(arr, 0, 10); mySort(arr, 0, 10); cout << "排序後:"; print(arr, 0, 10); } int main() { test1(); test2(); return 0; }
•結尾
咳咳,本次內容到此結束,完結撒花。