南天門日月卦長
如果現在有這些陣列需要排序:
難道有幾個資料型別就要寫幾個sort嗎?
void int_sort(int s[],int n); void char_sort(char s[],int n); void double_sort(double s[],int n); void float_sort(float s[],int n); void long_long_sort(long long s[],int n); //...
這些sort雖然資料型態不一樣
但是程式碼的結構卻是一模一樣的
在本小節中
各位將看到古人們怎麼解決以上的問題
因為有些難度
想跳過的人可以直接去看下一章節的內容
如果你寫的程式長這樣:
#define mul(x,y) (x*y) int main(){ cout << mul(3561,2) << '\n'; }
電腦(編譯器)看到的其實是這樣
int main(){ cout << (3561*2) << '\n'; }
如果有好幾行要define的話
可以利用反斜線'\'
來進行換行
#define swap(a,b){\ auto tmp = a;\ a = b;\ b = tmp;\ } int main(){ int x = 1, y = 2; swap(x, y); cout << x << ' ' << y << endl; }
int main(){ int x = 1, y = 2; { auto tmp = x; x = y; y = tmp; } cout << x << ' ' << y << endl; }
各位覺得如果我這樣寫會發生什麼事呢?
#define mul(x,y) (x*y) int main(){ cout << mul(3562-1,1+1) << '\n'; }
要注意#define
只是做字串取代而已
int main(){ cout << (3562-1*1+1) << '\n'; //3562-1*1+1 = 3562!! }
#include<iostream> using namespace std; #define max_func(func_name)\ int func_name(int a, int b){\ return a < b ? b : a;\ } max_func(myMax) int main(){ cout << myMax(7122, 2217); }
#include<iostream> using namespace std; int myMax(int a, int b){ return a < b ? b : a; } int main(){ cout << myMax(7122, 2217); }
利用define的性質
我們可以稍微簡化產生不同型態sort的方法
#define make_sort(Type, func_name)\ void func_name(Type s[], int n){\ for(int i=1; i<n; ++i)\ for(int j=i; j && s[j]<s[j-1]; --j)\ swap(s[j],s[j-1]);\ } make_sort(int, int_sort) make_sort(double, double_sort)
void int_sort(int s[], int n){ for(int i=1; i<n; ++i) for(int j=i; j && s[j]<s[j-1]; --j) swap(s[j],s[j-1]); } void double_sort(double s[], int n){ for(int i=1; i<n; ++i) for(int j=i; j && s[j]<s[j-1]; --j) swap(s[j],s[j-1]); }
剛剛教的define還是太麻煩了
而且好難
template
又稱「通用函式」(Generic Function)
想像 Type 可以是int, double, char …
這樣只要寫一個函式就好了!
template<typename Type> void mySort(Type s[], int n){ for(int i=1; i<n; ++i) for(int j=i; j && s[j]<s[j-1]; --j) swap(s[j],s[j-1]); } int main(){ int s[] = {7, 1, 2, 2}; mySort(s, 4); }
在你想做成模板的函數前面加上template<>就行了
T會根據呼叫函數時傳入的input變成不同的形態
template<typename T> T func_name(T input){ //do something }
template<typename T> T add(T a, T b){ return a+b; } int main(){ int int_a = 7022,int_b = 100; double d_a = 0.1, d_b = 7.022; cout << add(int_a, int_b) << '\n';// 7122 cout << add(d_a, d_b) << '\n';// 7.122 }
同時有好幾個型態時可以用逗號','
隔開
template<typename T, typename G> int func_name(T a, G b){ //do something }
template<typename T, typename G> int add(T a, G b,double c){ return a+b+c; } int main(){ int int_a = 7022; double d_b = 99.7122; cout << add(int_a, d_b, 0.5) << '\n';// 7122 }
以下的code會編譯失敗
因為編譯器不知道G到底是甚麼型態
template<typename T, typename G> G add(T a, T b){ G res = a+b;// G到底是甚麼型態? return res; } int main(){ double d_a = 0.1, d_b = 7.022; cout << add(d_a, d_b) << '\n'; }
這種情況使用函數時要用角括號<>
告訴編譯器你想用的型態
template<typename T, typename G> G add(T a, T b){ G res = a+b;// G到底是甚麼型態? return res; } int main(){ double d_a = 0.1, d_b = 7.022; cout << add<double, double>(d_a, d_b) << '\n'; cout << add<double, int>(d_a, d_b) << '\n'; cout << add<int, double>(d_a, d_b) << '\n'; }
又稱「通用類別」(Generic class)
想像 Type 可以是int, double, char …
這樣只要寫一個struct/class就好了!
template<typename Type> struct testType{ Type t; int id; }; int main(){ testType<double> data; data.t = 0.7122; data.id = 7122; }
在想做成模板的struct/class前面加上template<>
使用時要用**角括號<>
**告訴編譯器你T想用的型態
template<typename T> struct testType{ T t; int id; };
template<typename T> struct testType{ T t; int id; testType(T t, int id): t(t), id(id){} }; int main(){ testType<double> data(0.7122, 7122); cout << data.t << ' ' << data.id; }
當然和Function template一樣可以支援好幾個型態
template<typename T, typename G> struct Jinkela{ T NPK; G shengdiyage; }; Jinkela<int, string> jinkela; int main(){ jinkela.NPK = 30000; jinkela.shengdiyage = "American.shengdiyage"; }
在下一章節中,我們會介紹強大的STL
標準模板庫(Standard Template Library)
會用到大量template的概念
一定要熟悉喔