Step By Step(C++模板重載和特化)


一、模板函數重載:

    函數重載是一個非常通用亦非常容易理解的編程基礎概念,既函數名相同而函數簽名不同的一組函數,在實際的調用中,編譯器會根據函數參數的不同自動選擇最為合適且最為特化的函數。在推演的過程中,如果出現多個函數均符合該調用規則,編譯器將根據其內置的特化規則,選擇最為特殊的函數作為候選函數。然而如果仍有多個候選函數的話,編譯器將報出二義性錯誤。和普通函數一樣,在C++中模板函數也同樣支持函數重載的功能,甚至可以將模板函數與普通函數混合在一起,以達到更為靈活的函數重載的效果。
    在這里,我們對於函數重載的概念本身將不再做過多的贅述了,而是將重點放在模板函數重載的應用場景和應用技巧上。下面我將給出一個利用模板函數重載計算哈希值的代碼示例:

 1     #include <stdio.h>
 2     
 3     template<typename T> 
 4     int hash_code(T v) {
 5         return v.hashCode() * 2;
 6     }
 7     
 8     template<typename T>
 9     int hash_code(T* v) {
10         return v->hashCode();
11     }
12     
13     int hash_code(const int v) {
14         return v + 100;
15     }
16     
17     class HashClass {
18     public:
19         HashClass(int v) : _v(v) {}
20         int hashCode() {
21             return _v + 200;
22         }
23     
24     private:
25         int _v;
26     };
27     
28     int main() {
29         HashClass c1(10);  //調用的是template<typename T> int hash_code(T v)
30         printf("The hash value is %d\n",hash_code(c1));
31         HashClass c2(20);  //調用的是template<typename T> int hash_code(T* v)
32         printf("The hash value is %d\n",hash_code(&c2));
33         int i3 = 30;      //調用的是int hash_code(const int v)
34         printf("The hash value is %d\n",hash_code(i3));
35         return 0;
36     }
37     
38     //The hash value is 420
39     //The hash value is 220
40     //The hash value is 130

    在上面的示例代碼中,hash_code函數可以讓編譯器根據參數的不同選擇最為合適的候選函數。在這里模板函數和普通函數一同參與了函數重載。對於模板函數重載,主要應用於算法領域,既對於大多數的類型可以通過泛型算法以達到預期的效果,而對於特殊類型,則可以通過函數重載的方式,針對該類型實現另外一套更為高效的算法。
    
二、模板類特化:

    對於模板類而言,也同樣存在和模板函數重載類似的應用場景,但是在模板類中則是以模板類特化的方式存在。在下面的示例代碼為生產者-消費者的任務緩沖隊列,當清空隊列中的已有元素時,亦需考慮如何釋放元素對象本身可能占用的系統資源。這里會根據不同的元素類型,給出不同的元素釋放類。

 1     #include <stdio.h>
 2     #include <vector>
 3     
 4     using namespace std;
 5     
 6     class Runnable {  
 7     public:
 8         virtual void release() {
 9             delete this;
10         }
11     };
12     
13     class Closable {
14     public:
15         virtual void close() {
16             _db.close();
17             delete this;
18         }
19     private:
20         db_env _db;
21     };
22     
23     template<typename T>
24     class List {   //1
25     public:
26         void clear() { 
27             _taskList.clear();
28         }
29     private:
30         vector<T> _taskList;
31     };
32     
33     template<typename T>
34     class List<T*> {  //2
35     public:
36         void clear() {
37             for (int i = 0; i < _taskList.size(); ++i)
38                 delete _taskList[i];
39             _taskList.clear();
40         }
41     private:
42         vector<T*> _taskList;
43     };
44     
45     template<>
46     class List<char*> {  //3
47     public:
48         void clear() {
49             for (int i = 0; i < _taskList.size(); ++i)
50                 delete [] _taskList[i];
51             _taskList.clear();
52         }
53     private:
54         vector<char*> _taskList;
55     };
56     
57     template<>
58     class List<Runnable*> {  //4
59     public:
60         void clear() {
61             for (int i = 0; i < _taskList.size(); ++i)
62                 _taskList[i]->release();
63             _taskList.clear();
64         }
65     private:
66         vector<Runnable*> _taskList;
67     };
68     
69     template<>
70     class List<Closable*> {  //5
71     public:
72         void clear() {
73             for (int i = 0; i < _taskList.size(); ++i)
74                 _taskList[i]->close();
75             _taskList.clear();
76         }
77     private:
78         vector<Runnable*> _taskList;
79     };
80     
81     int main() {
82         List<Runnable*> listRunnable;  //調用No 4
83         List<Closable*> listClosable;  //調用No 5
84         List<int> listInt;             //調用No 1
85         List<int*> listIntPointer      //調用No 2
86         List<char*> listCharPointer;   //調用No 3
87         return 0;
88     }

    在上面的代碼示例中,編譯器會根據模板參數的不同而選擇不同的模板類,然而這一切對於調用者而言又是完全透明的,如果今后再增加新的特殊類型時,僅需為該類型實現一個新的特化類即可。需要說明的,該代碼片段完全是為了演示這個C++模板特征而編寫的,僅供參考。


免責聲明!

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



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