C++中的數據類模板


1,預備知識:

    1,模板參數可以是數值型參數(非類型參數):

       1,代碼示例:

1 template <typename T, int N> 
2 void func()
3 {
4     T a[N];  // 使用模板參數定義局部數組;
5 }
6            
7 func<double, 10>();  // 使用模板時,數值型參數必須是常量,不能是變量;

    2,數值型模板參數的限制:

       1,變量不能作為模板參數;

           1,是變量的話就不滿足准確確定的這個本質;

       2,浮點數不能作為模板參數;

           1,浮點數本身不精確;

       3,類對象不能作為模板參數;

           1,類對象編譯時不能唯一確定的,同變量一樣;

    3,數值型參數本質:模板參數是在編譯階段被處理的單元,因此,在編譯階段必須准確無誤的唯一確定;

          

2,有趣的面試題:

    1,用你覺得最高效的方法求 1 + 2 + 3 + ... + N 的值;

       1,等差數列和的方式;

       2,見下面實例;

   

3,數值型模板參數編程實驗:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 /* 驗證上面的預備知識 */
 7 template
 8 < typename T, int N >  // 這里用成 double 后,編譯器顯示:error: 'double' is not a valid type for a template constant parameter
 9 void func()
10 {
11     T a[N] = {0};
12     
13     for(int i=0; i<N; i++)
14     {
15         a[i] = i;
16     }
17     
18     for(int i=0; i<N; i++)
19     {
20         cout << a[i] << endl;
21     }
22 }
23 
24 /* 用最高效的方法驗證從 1 加到 n 的和;不用循環和等差數列求和公式 */
25 template
26 < int N >
27 class Sum
28 {
29 public:
30     // static const int VALUE = 0;  // static 后是想定義常量,被 static 修飾后要么放入符號表、要么放到全局數據區; 這個時候 VALUE 已經確定了值,所以直接進入符號表(符號表存儲在哪里呢);又因為 VALUE 被 static 修飾了,所以 VALUE 被放入全局數據區;
31     static const int VALUE = Sum<N-1>::VALUE + N;  // 遞歸定義
32 };
33 
34 /* 定義上述模板類的特化實現,實現遞歸出口 */
35 template
36 < >
37 class Sum < 1 >
38 {
39 public:
40     static const int VALUE = 1;
41 };
42 
43 int main()
44 {
45     func<int, 10>();  // 打印 0 到 9 這十個數字;這里如果模板參數類型為 double,編譯器顯示:error: no matching function for call to 'func()';
46     
47     int a = 10;
48     func<int, a>();  // 在這一行編譯器顯示:
49        // error: 'a' cannot appear in a constant-expression
50        // error: no matching function for call to 'func()'
51                      
52     cout << "1 + 2 + 3 + ... + 10 = " << Sum<10>::VALUE << endl;  // 55;這里沒有加減乘除法,也沒有函數調用和循環,這里VALUE 是常量,並在編譯的時候已經確定,這里效率是最高的;
53     cout << "1 + 2 + 3 + ... + 100 = " << Sum<100>::VALUE << endl;   // 5050
54     
55     return 0;
56 }    

    1,這里的相加求和是在編譯器編譯程序的時候完成的,編譯完程序后,要求的和的值已經確定,在運行的時候,就直接可以訪問這個值,不需要做任何的運算和循環,因此效率最高;

    2,這個最高效的求和依賴了模板技術、模板特化技術、數值型模板參數技術;

    3,可以舉一反三,得到更多高效的程序寫法;

   

4,數組模板類編程實驗:

    1,Array.h 文件:

 1 #ifndef _ARRAY_H_  // 防止多次包含頭文件;
 2 #define _ARRAY_H_
 3 
 4 template
 5 < typename T, int N >  // 數組元素的類型和大小;
 6 class Array
 7 {
 8     T m_array[N];  // 定義一個實際的數組;
 9 public:
10     int length();
11     bool set(int index, T value);
12     bool get(int index, T& value);
13     T& operator[] (int index);
14     T operator[] (int index) const;  // 數組類對象有可能是 const 對象,這個時候就只能調用 const 函數,所以要定義這個;const 函數只能返回值,不能返回引用;
15     virtual ~Array();  // 有可能被繼承
16 };
17 
18 /* 模板類要放在一個文件中,所以實現在下面實現 */
19 
20 template
21 < typename T, int N >
22 int Array<T, N>::length()
23 {
24     return N;
25 }
26 
27 template
28 < typename T, int N >
29 bool Array<T, N>::set(int index, T value)
30 {
31     bool ret = (0 <= index) && (index < N);
32     
33     if( ret )
34     {
35         m_array[index] = value;
36     }
37     
38     return ret;
39 }
40 
41 template
42 < typename T, int N >
43 bool Array<T, N>::get(int index, T& value)
44 {
45     bool ret = (0 <= index) && (index < N);
46     
47     if( ret )
48     {
49         value = m_array[index];
50     }
51     
52     return ret;
53 }
54 
55 template
56 < typename T, int N >
57 T& Array<T, N>::operator[] (int index)
58 {
59     return m_array[index];
60 }
61 
62 template
63 < typename T, int N >
64 T Array<T, N>::operator[] (int index) const
65 {
66     return m_array[index];
67 }
68 
69 template
70 < typename T, int N >
71 Array<T, N>::~Array()
72 {
73 
74 }
75 
76 #endif

    2,應用:

 1 #include <iostream>
 2 #include <string>
 3 #include "Array.h"
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     Array<double, 5> ad;
10     
11     for(int i=0; i<ad.length(); i++)
12     {
13         ad[i] = i * i;
14     }
15     
16     for(int i=0; i<ad.length(); i++)
17     {
18         cout << ad[i] << endl;
19     }
20     
21     return 0;
22 }

   

5,堆數組模板類編程實驗:

 1,HeapArray.h 文件:

  1 #ifndef _HEAPARRAY_H_
  2 #define _HEAPARRAY_H_
  3 
  4 template
  5 < typename T >
  6 class HeapArray
  7 {
  8 private:
  9     int m_length;
 10     T* m_pointer;
 11     
 12     HeapArray(int len);
 13     HeapArray(const HeapArray<T>& obj);
 14     bool construct();
 15 public:
 16     static HeapArray<T>* NewInstance(int length); 
 17     int length();
 18     bool get(int index, T& value);
 19     bool set(int index ,T value);
 20     T& operator [] (int index);
 21     T operator [] (int index) const;  // 有可能有 const 對象;
 22     HeapArray<T>& self();
 23     ~HeapArray();  // 這個時候構造函數是 private 的,也就是 HeapArray 類不希望被繼承,所以說沒有必要將它聲明為 virtual 的;
 24 };
 25 
 26 /* 實現要在同一個文件中 */
 27 
 28 template
 29 < typename T >
 30 HeapArray<T>::HeapArray(int len)
 31 {
 32     m_length = len;
 33 }
 34 
 35 template
 36 < typename T >
 37 bool HeapArray<T>::construct()
 38 {   
 39     m_pointer = new T[m_length];
 40     
 41     return m_pointer != NULL;
 42 }
 43 
 44 template
 45 < typename T >
 46 HeapArray<T>* HeapArray<T>::NewInstance(int length) 
 47 {
 48     HeapArray<T>* ret = new HeapArray<T>(length);
 49     
 50     if( !(ret && ret->construct()) ) 
 51     {
 52         delete ret;
 53         ret = 0;
 54     }
 55         
 56     return ret;
 57 }
 58 
 59 template
 60 < typename T >
 61 int HeapArray<T>::length()
 62 {
 63     return m_length;
 64 }
 65 
 66 template
 67 < typename T >
 68 bool HeapArray<T>::get(int index, T& value)
 69 {
 70     bool ret = (0 <= index) && (index < length());
 71     
 72     if( ret )
 73     {
 74         value = m_pointer[index];
 75     }
 76     
 77     return ret;
 78 }
 79 
 80 template
 81 < typename T >
 82 bool HeapArray<T>::set(int index, T value)
 83 {
 84     bool ret = (0 <= index) && (index < length());
 85     
 86     if( ret )
 87     {
 88         m_pointer[index] = value;
 89     }
 90     
 91     return ret;
 92 }
 93 
 94 template
 95 < typename T >
 96 T& HeapArray<T>::operator [] (int index)
 97 {
 98     return m_pointer[index];
 99 }
100 
101 template
102 < typename T >
103 T HeapArray<T>::operator [] (int index) const
104 {
105     return m_pointer[index];
106 }
107 
108 template
109 < typename T >
110 HeapArray<T>& HeapArray<T>::self()
111 {
112     return *this;
113 }
114 
115 template
116 < typename T >
117 HeapArray<T>::~HeapArray()
118 {
119     delete[]m_pointer;
120 }
121 
122 #endif

    2,應用:

 1 #include <iostream>
 2 #include <string>
 3 #include "HeapArray.h"
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {   
 9     HeapArray<char>* pai = HeapArray<char>::NewInstance(10);
10     
11     if( pai != NULL )
12     {
13         HeapArray<char>& ai = pai->self();
14         
15         for(int i=0; i<ai.length(); i++)
16         {
17             ai[i] = i + 'a';
18         }
19         
20         for(int i=0; i<ai.length(); i++)
21         {
22             cout << ai[i] << endl;
23         }
24     }
25     
26     delete pai;
27     
28     return 0;
29 }

   

6,小結:

    1,模板參數可以是數值型參數;

    2,數值型模板參數必須在編譯期間唯一確定;

    3,數組類模板是基於數值型模板參數實現的;

    4,數組類模板是簡易的線性表數據結構;


免責聲明!

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



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