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

[来源] 达内    [编辑] 达内   [时间]2012-09-13

函数重载是一个非常通用亦非常容易理解的编程基础概念,既函数名相同而函数签名不同的一组函数,在实际的调用中,编译器会根据函数参数的不同自动选择最为合适且最为特化的函数。

一、模板函数重载:

& nbsp;   函数重载是一个非常通用亦非常容易理解的编程基础概念,既函数名相同而函数签名不同的一组函数,在实际的调用中,编译器会根据函数参数的不同自动选择最为合适且最为特化的函数。在推演的过程中,如果出现多个函数均符合该调用规则,编译器将根据其内置的特化规则,选择最为特殊的函数作为候选函数。然而如果仍有多个候选函数的话,编译器将报出二义性错误。和普通函数一样,在C++中模板函数也同样支持函数重载的功能,甚至可以将模板函数与普通函数混合在一起,以达到更为灵活的函数重载的效果。
    在这里,我们对于函数重载的概念本身将不再做过多的赘述了,而是将重点放在模板函数重载的应用场景和应用技巧上。下面我将给出一个利用模板函数重载计算哈希值的代码示例:

< div style="background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; max-width: 900px; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
 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
< p style="margin: 5px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); ">     在上面的示例代码中,hash_code函数可以让编译器根据参数的不同选择最为合适的候选函数。在这里模板函数和普通函数一同参与了函数重载。对于模板函数重载,主要应用于算法领域,既对于大多数的类型可以通过泛型算法以达到预期的效果,而对于特殊类型,则可以通过函数重载的方式,针对该类型实现另外一套更为高效的算法。
    
二、模板类特化:

    对于模板类而言,也同样存在和模板函数重载类似的应用场景,但是在模板类中则是以模板类特化的方式存在。在下面的示例代码为生产者-消费者的任务缓冲队列,当清空队列中的已有元素时,亦需考虑如何释放元素对象本身可能占用的系统资源。这里会根据不同的元素类型,给出不同的元素释放类。

< div style="background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; max-width: 900px; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_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*> {  //
347
     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     }
< p style="margin: 5px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); ">    在上面的代码示例中,编译器会根据模板参数的不同而选择不同的模板类,然而这一切对于调用者而言又是完全透明的,如果今后再增加新的特殊类型时,仅需为该类型实现一个新的特化类即可。需要说明的,该代码片段完全是为了演示这个C++模板特征而编写的,仅供参考。

资源下载