C++中類模板的深入理解


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,工程中使用模板特化代替類(函數)重定義;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM