1,多參數類模板:
1,類模板可以定義任意多個不同的類型參數;
1,代碼示例:
1 template <typename T1, typename T2> 2 class Test 3 { 4 public: 5 void add(T1 a, T2 a); 6 }; 7 8 Test<int, float> t;
2,類模板可以被特化:
1,指定類模板的特定實現;
2,部分類型參數必須顯示指定;
3,根據類型參數分開實現類模板;
3,類模板的特化類型:
1,部分特化 - 用特定規則約束類型參數;
1,上面的為部分特化;
2,完全特化 - 完全顯示指定類型參數;
4,類模板的特化編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 template 7 < typename T1, typename T2 > 8 class Test 9 { 10 public: 11 void add(T1 a, T2 b) 12 { 13 cout << "void add(T1 a, T2 b)" << endl; 14 cout << a + b << endl; 15 } 16 }; 17 18 /* 關於上述第一個類模板的特殊實現,關於指針的特化實現 */ 19 template 20 < typename T1, typename T2 > 21 class Test < T1*, T2* > // 關於指針的特化實現 22 { 23 public: 24 void add(T1* a, T2* b) 25 { 26 cout << "void add(T1* a, T2* b)" << endl; 27 cout << *a + *b << endl; 28 } 29 }; 30 31 /* 定義上述第一個類模板的特殊實現,即當Test 類模板的兩個類型參數完全相同時,使用這個實現;編譯器並不認為在這里重新定義了一個新的模板,它認為這里是在定義第一個類模板的特殊實現;這里是部分特化; 32 */ 33 template 34 < typename T > 35 class Test < T, T > // Test 類模板的兩個類型參數完全相同時,使用這個實現; 36 { 37 public: 38 void add(T a, T b) 39 { 40 cout << "void add(T a, T b)" << endl; 41 cout << a + b << endl; 42 } 43 44 void print() // 特化實現可以重新定義新的函數; 45 { 46 cout << "class Test < T, T >" << endl; 47 } 48 }; 49 50 /* 定義上述第一個類模板的特殊實現,當 T1 == void* 並且 T2 == void* 時,使用這個實現; */ 51 template 52 < > // 沒有泛指類型; 53 class Test < void*, void* > // 當 T1 == void* 並且 T2 == void* 時 54 { 55 public: 56 void add(void* a, void* b) 57 { 58 cout << "void add(void* a, void* b)" << endl; 59 cout << "Error to add void* param..." << endl; 60 } 61 }; 62 63 int main() 64 { 65 Test<int, float> t1; // 使用第一個類模板; 66 Test<long, long> t2; // 使用第三個類模板,特化實現; 67 Test<void*, void*> t3; // 使用第四個類模板,特化實現; 68 69 t1.add(1, 2.5); // void add(T1 a, T2 b) 3.5; 70 71 t2.add(5, 5); // void add(T a, Tb) 10; 72 t2.print(); // class Test < T, T > 73 74 t3.add(NULL, NULL); // void add(void* a, void* b);Error to add void* param...; 75 76 Test<int*, double*> t4; // 未有定義指針特化時,編譯器顯示 14 行:error: invalid operands of types 'int*' and 'double*' to binary 'operator+'; 77 // 特化指針后,打印 void add(T1* a, T2* b); 78 int a = 1; 79 double b = 0.1; 80 81 t4.add(&a, &b); // 1.1 82 83 return 0; 84 }
1,類模板的特化實現表象上面好像定義了不同的類模板,但其實我們僅僅是根據需要將一個類模板分開成不同的情況來實現;
2,編譯器編譯過后根據我們使用的類型參數來決定究竟是哪一種實現;
5,類模板特化注意事項:
1,特化只是模板的分開實現:
1,本質上是同一個類模板;
2,僅僅是將模板根據需要分開來實現;
2,特化類模板的使用方式是統一的;
1,必須顯示指定每一個類型參數;
2,類模板特化與重定義有區別嗎?函數模板可以特化嗎?
1,有區別;
3,特化的深度分析:
1,重定義和特化的不同:
1,重定義:
1,一個類模板和一個新類(或者兩個類模板);
1,重定義本質是要么是實現了兩個類模板,要么是一個類模板加上 一個新的類;
2,特化本質是只實現同一個類模板,特化的目的僅僅是考慮一些特殊的情況類模板應該如何工作;
2,使用的時候需要考慮如何選擇的問題;
1,使用的時候沒有統一的方式,要選擇用類模板的種類或用新的類;
2,特化:
1,以統一的方式使用類模板和特化類;
2,編譯器自動優先選擇特化類;
1,能用特化就不要重定義;
2,函數模板只支持類型參數完全特化:
1,代碼示例:
1 template < typename T> // 函數模板定義 2 bool Equal(T a, T b) 3 { 4 return a == b; 5 } 6 7 template < > // 函數模板完全特化 8 bool Equal<void *>(void* a, void* b) 9 { 10 return a == b; 11 }
3,特化的深入理解編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 /* 以下是類模板的重定義實現 */ 7 template 8 < typename T1, typename T2 > 9 class Test 10 { 11 public: 12 void add(T1 a, T2 b) 13 { 14 cout << "void add(T1 a, T2 b)" << endl; 15 cout << a + b << endl; 16 } 17 }; 18 19 /* 20 template 21 < > 22 class Test < void*, void* > // 當 T1 == void* 並且 T2 == void* 時 23 { 24 public: 25 void add(void* a, void* b) 26 { 27 cout << "void add(void* a, void* b)" << endl; 28 cout << "Error to add void* param..." << endl; 29 } 30 }; 31 */ 32 33 /* 類模板的重定義,重新實現上面注釋的模板特化,處理指針相加 */ 34 class Test_Void 35 { 36 public: 37 void add(void* a, void* b) 38 { 39 cout << "void add(void* a, void* b)" << endl; 40 cout << "Error to add void* param..." << endl; 41 } 42 }; 43 44 45 /* 以下是函數模板的特化實驗 */ 46 47 template 48 < typename T > 49 bool Equal(T a, T b) 50 { 51 cout << "bool Equal(T a, T b)" << endl; 52 53 return a == b; 54 } 55 56 /* 函數完全特化解決浮點數比較問題 */ 57 template 58 < > 59 bool Equal<double>(double a, double b) 60 { 61 const double delta = 0.00000000000001; 62 double r = a - b; 63 64 cout << "bool Equal<double>(double a, double b)" << endl; 65 66 return (-delta < r) && (r < delta); 67 } 68 69 /* 直接重載 */ 70 bool Equal(double a, double b) 71 { 72 const double delta = 0.00000000000001; 73 double r = a - b; 74 75 cout << "bool Equal(double a, double b)" << endl; 76 77 return (-delta < r) && (r < delta); 78 } 79 80 int main() 81 { 82 Test<void*, void*> t3; // 這里錯誤了,要用 Test_Void t3; 這樣的 定義方式,因為重定義了類的實現方式,注銷了模板特化方式;寫代碼時,要時刻考慮究竟是要使用類模板 還是要使用新類,這就是弊端,所以能特化時,就不要重新定義、重新實現; 83 84 cout << Equal( 1, 1 ) << endl; // bool Equal(T a, T b) 1 85 cout << Equal<>( 0.001, 0.001 ) << endl; // 用相等符號比較兩個浮點數是否相等是有問題的;用了特化后:bool Equal<double>(double a, double b) 1 86 cout << Equal( 0.001, 0.001 ) << endl; // bool Equal(double a, double b) 1;這里調用全局重載函數,因為編譯器會優先尋找全局重載函數; 87 88 return 0; 89 }
4,工程中的建議:
1,當需要重載函數模板時,優先考慮使用模板特化;當模板特化無法滿足需求,再使用函數重載!
4,小結:
1,類模板可以定義任意多個不同的類型參數;
2,類模板可以被部分特化和完全特化;
3,特化的本質是模板的分開實現;
4,函數模板只支持完全特化;
5,工程中使用模板特化代替類(函數)重定義;