小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

(C 模板類)

 閑來看看 2013-02-28

和函數(shù)一樣,C++中的class也可以類型參數(shù)化,其中容器類是極具這一特征的。對(duì)于模板類的基本定義和使用,可以參考STL,這里就不做過多的贅述了。下面將主要介紹一下與其相關(guān)的高級(jí)實(shí)用特征。

一、模板的特化:

    這里可以先將類模板特化與面向?qū)ο笾械亩鄳B(tài)進(jìn)行一個(gè)簡(jiǎn)單的比較,這樣可以便于我們對(duì)它的理解,也同樣有助于指導(dǎo)我們?cè)趯?shí)際的開發(fā)中應(yīng)用這一C++技巧。眾所周知,對(duì)于多態(tài)而言,提供的是統(tǒng)一的接口和不同的實(shí)現(xiàn)類實(shí)例,其最終的行為將取決于實(shí)現(xiàn)類中的實(shí)現(xiàn),相信每一個(gè)有面向?qū)ο蠡A(chǔ)的開發(fā)者對(duì)于這一概念并不陌生。而模板特化則要求必須提供一個(gè)標(biāo)準(zhǔn)的模板類(等同于多態(tài)中的接口),與此同時(shí)再為不同的類型提供不同的特化版本。在模板特化類中,我們首先需要保證類名是相同的,只是模板參數(shù)不再使用抽象的類型,而是直接使用具體的類型來實(shí)例化該模板類。在調(diào)用時(shí),編譯器會(huì)根據(jù)調(diào)用時(shí)的類型參數(shù)自動(dòng)選擇最為合適的模板類,即如果有特化模板類中的類型參數(shù)和當(dāng)前調(diào)用類型相匹配的話,則首選該特化模板類,否則選擇最初的標(biāo)準(zhǔn)模板類。見如下用例(請(qǐng)注意代碼中的說明性注釋)

  1     #include <stdio.h>
  2     #include <string.h>
  3     
  4     //1. 這里我們先聲明了一個(gè)通用類型的模板類。這里要有類型參數(shù)必須包含hashCode()方法。
  5     //否則,該類型在編譯期實(shí)例化時(shí)將會(huì)導(dǎo)致編譯失敗。
  6     template <typename T>
  7     class CalcHashClass { //該類為標(biāo)準(zhǔn)模板類(等同于多態(tài)中的接口)
  8     public:
  9         CalcHashClass(T const& v) : _value(v) {
 10         }
 11         int hashCode() {
 12             printf("This is 'template <typename T> class CalcHashClass'.\n");
 13             return _value.hashCode() + 10000;
 14         }
 15     private:
 16         T _value;
 17     };
 18     
 19     //2. int類型實(shí)例化特化模板類。
 20     template <>
 21     class CalcHashClass<int> {
 22     public:
 23         CalcHashClass(int const& v) : _value(v) {
 24         }
 25         int hashCode() {
 26             printf("This is 'template <> class CalcHashClass<int>'.\n");
 27             return _value * 101;
 28         }
 29     private:
 30         int _value;
 31     };
 32     
 33     //3. const char*類型實(shí)例化的特化模板類
 34     template<>
 35     class CalcHashClass<const char*> {
 36     public:
 37         CalcHashClass(const char* v) {
 38             _v = new char[strlen(v) + 1];
 39             strcpy(_v,v);
 40         }
 41         ~CalcHashClass() {
 42             delete [] _v;
 43         }
 44         int hashCode() {
 45             printf("This is 'template <> class CalcHashClass<const char*>'.\n");
 46             int len = strlen(_v);
 47             int code = 0;
 48             for (int i = 0; i < len; ++i)
 49                 code += (int)_v[i];
 50             return code;
 51         }
 52     
 53     private:
 54         char* _v;
 55     };
 56     
 57     //4. 輔助函數(shù),用于幫助調(diào)用者通過函數(shù)的參數(shù)類型自動(dòng)進(jìn)行類型推演,以讓編譯器決定該
 58     //實(shí)例化哪個(gè)模板類。這樣就可以使調(diào)用者不必在顯示指定模板類的類型了。這一點(diǎn)和多態(tài)有
 59     //點(diǎn)兒類似。
 60     template<typename T>
 61     inline int CalcHashCode(T v) {
 62         CalcHashClass<T> t(v);
 63         return t.hashCode();
 64     }
 65     
 66     //5. 給出一個(gè)范例類,該類必須包含hashCode方法,否則將造成編譯錯(cuò)誤。
 67     class TestClass {
 68     public:
 69         TestClass(const char* v) {
 70             _v = new char[strlen(v) + 1];
 71             strcpy(_v,v);
 72         }
 73         ~TestClass() {
 74             delete [] _v;
 75         }
 76     public:
 77         int hashCode() {
 78             int len = strlen(_v);
 79             int code = 0;
 80             for (int i = 0; i < len; ++i)
 81                 code += (int)_v[i];
 82             return code;
 83         }
 84     private:
 85         char* _v;
 86     };
 87     
 88     int main() {
 89         TestClass tc("Hello");
 90         CalcHashClass<TestClass> t1(tc);
 91         printf("The hashcode is %d.\n",t1.hashCode());
 92         //這里由于為模板類TestClass提供了基于int類型的模板特化類,因此編譯器會(huì)自動(dòng)選擇
 93         //更為特化的模板類作為t2的目標(biāo)類。
 94         CalcHashClass<int> t2(10);
 95         printf("The hashcode is %d.\n",t2.hashCode());
 96     
 97         //在上面的示例中,我們通過顯示的給出類型信息以實(shí)例化不同的模板類,這是因?yàn)槟0孱?
 98         //的類型信息是無法像模板函數(shù)那樣可以通過函數(shù)參數(shù)進(jìn)行推演的,為了彌補(bǔ)這一缺失,我們可以
 99         //通過一個(gè)額外的模板函數(shù)來幫助我們完成這一功能。事實(shí)上,這一技巧在Thinking in Java中
100         //也同樣給出了。
101         printf("Ths hashcode is %d.\n",CalcHashCode(10));
102         printf("Ths hashcode is %d.\n",CalcHashCode("Hello"));
103         return 0;
104     }
105     //This is 'template <typename T> class CalcHashClass'.
106     //The hashcode is 10500.
107     //This is 'template <> class CalcHashClass<int>'.
108     //The hashcode is 1010.
109     //This is 'template <> class CalcHashClass<int>'.
110     //Ths hashcode is 1010.
111     //This is 'template <> class CalcHashClass<const char*>'.
112     //Ths hashcode is 500.

    通過上面的示例可以看出,模板特化是依賴于編譯器在編譯期動(dòng)態(tài)決定該使用哪個(gè)特化類,或是標(biāo)準(zhǔn)模板類的。相比于多態(tài)的后期動(dòng)態(tài)綁定,該方式的運(yùn)行效率更高,同時(shí)靈活性也沒有被更多的犧牲。
    下面將給出一個(gè)結(jié)合模板特化和多態(tài)的示例(請(qǐng)注意代碼中的說明性注釋)

 
 1     #include <stdio.h>
 2     #include <string.h>
 3     
 4     //1. 定義一個(gè)接口
 5     class BaseInterface {
 6     public:
 7         virtual ~BaseInterface() {}
 8         virtual void doPrint() = 0;
 9     };
10     
11     //2. 標(biāo)準(zhǔn)模板類繼承該接口,同時(shí)給出自己的doPrint()實(shí)現(xiàn)。
12     template<typename T>
13     class DeriveClass : public BaseInterface {
14     public:    
15         void doPrint() {
16             printf("This is 'template<typename T> class DeriveClass'.\n");
17         }
18     };
19     
20     //3. 基于int類型特化后的DeriveClass模板類,同樣繼承了該接口,也給出了自己的DoPrint()實(shí)現(xiàn)。
21     template<>
22     class DeriveClass<int> : public BaseInterface {
23     public:    
24         void doPrint() {
25             printf("This is 'template<> class DeriveClass<int>'.\n");
26         }
27     };
28     
29     //4. 對(duì)象創(chuàng)建輔助函數(shù),該函數(shù)可以通過參數(shù)類型的不同,實(shí)例化不同的接口子類。
30     template<typename T>
31     inline BaseInterface* DoTest(T t) {
32         return new DeriveClass<T>;
33     }
34     
35     int main() {
36         BaseInterface* b1 = DoTest(4.5f);
37         b1->doPrint();
38         BaseInterface* b2 = DoTest(5);
39         b2->doPrint();
40         delete b1;
41         delete b2;
42         return 0;
43     }
44     //This is 'template<typename T> class DeriveClass'.
45     //This is 'template<> class DeriveClass<int>'.    

   
二、模板部分特化:

    有的書中將其翻譯成模板偏特化,或者是模板的局部特化,但含義都是相同的。為了便于理解,我們可以將上面的模板特化稱為模板全部特化,即模板類的類型參數(shù)全部被特化了。顧名思義,模板部分特化只是將其中一部分類型參數(shù)進(jìn)行了特化聲明,因此也可以將模板特化視為模板部分特化的一種特殊形式。由于應(yīng)用場(chǎng)景基本相同,因此下面的代碼將僅僅給出最基本的示例和注釋說明,以幫助大家熟悉他的語法即可:

 
 1     //1. 標(biāo)準(zhǔn)模板類。
 2     template<typename T1, typename T2>
 3     class MyClass {
 4         ... ...
 5     };
 6     //2. 兩個(gè)模板參數(shù)具有相同類型的部分特化類。
 7     template<typename T>
 8     class MyClass<T,T> {
 9         ... ...
10     }
11     //3. 第二個(gè)類型參數(shù)是int
12     template<typename T>
13     class MyClass<T,int> {
14         ... ...
15     }
16     //4. 兩個(gè)模板參數(shù)都是指針。
17     template<typename T1,typename T2>
18     class MyClass<T1*,T2*> {
19         ... ...
20     }
21     //5. 兩個(gè)模板參數(shù)都是相同類型的指針。
22     template<typename T>
23     class MyClass<T*,T*> {
24         ... ...
25     }
26     //6. 調(diào)用示例代碼。
27     int main() {
28         MyClass<int,float> c1;         //調(diào)用MyClass<T1,T2>
29         MyClass<float,float> c2;    //調(diào)用MyClass<T,T>
30         MyClass<float,int> c3;      //調(diào)用MyClass<T,int>
31         MyClass<int*,float*> c4;    //調(diào)用MyClass<T1*,T2*> 
32         MyClass<int*,int*> c5;      //調(diào)用MyClass<T*,T*>
33         return 0;
34     }
 

   
三、缺省模板實(shí)參:

    和函數(shù)的缺省參數(shù)一樣,C++的模板也同樣支持缺省類型參數(shù)。

 
 1     //1. 第二個(gè)類型參數(shù)的缺省值是vector<T>
 2     template<typename T, typename T2 = std::vector<T> >
 3     class MyClass {
 4         ... ... 
 5     }
 6     int main() {
 7         MyClass<int> c1;            //第二個(gè)類型參數(shù)是vector<int> 
 8         MyClass<int,list<int> > c2; //第二個(gè)類型參數(shù)是list<int> 
 9         return 0;
10     }
 

    這種使用缺省模板參數(shù)的代碼,在STL中比比皆是。
    
四、非類型模板參數(shù):

    模板的類型參數(shù)不僅僅可以是類型,也可以是常量,但是常量本身的類型是有限制的,不是所有類型的常量都可以,目前只是整型常量和外部鏈接對(duì)象的指針可以,而浮點(diǎn)型等其他原始類型,或自定義類型均不可。

 
 1     template<typename T, int MAXSIZE>
 2     class MyContainer {
 3     public:
 4         int capacity() const { return MAXSIZE; }
 5         ... ...
 6     private:
 7         T elements[MAXSIZE];
 8     };
 9      
10     int main() {
11         MyContainer<int,50> c1;
12         return 0;
13     }
14     和普通類型模板一樣,非類型模板參數(shù)也可以有缺省值,如:
15     template<typename T, int MAXSIZE = 10>
16     class MyContainer {
17     public:
18         int capacity() const { return MAXSIZE; }
19         ... ...
20     private:
21         T elements[MAXSIZE];
22     };

   
    最后需要說明的是,不管是普通模板類還是非類型模板類,只要其類型不同,或是常量值不同,就不能將其視為相同類型的對(duì)象,這一點(diǎn)同樣適用于模板函數(shù)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多