日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

(C 模板類)

 閑來看看 2013-02-28

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

一、模板的特化:

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

  1     #include <stdio.h>
  2     #include <string.h>
  3     
  4     //1. 這里我們先聲明了一個通用類型的模板類。這里要有類型參數(shù)必須包含hashCode()方法。
  5     //否則,該類型在編譯期實例化時將會導(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類型實例化特化模板類。
 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*類型實例化的特化模板類
 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ù)類型自動進(jìn)行類型推演,以讓編譯器決定該
 58     //實例化哪個模板類。這樣就可以使調(diào)用者不必在顯示指定模板類的類型了。這一點和多態(tài)有
 59     //點兒類似。
 60     template<typename T>
 61     inline int CalcHashCode(T v) {
 62         CalcHashClass<T> t(v);
 63         return t.hashCode();
 64     }
 65     
 66     //5. 給出一個范例類,該類必須包含hashCode方法,否則將造成編譯錯誤。
 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類型的模板特化類,因此編譯器會自動選擇
 93         //更為特化的模板類作為t2的目標(biāo)類。
 94         CalcHashClass<int> t2(10);
 95         printf("The hashcode is %d.\n",t2.hashCode());
 96     
 97         //在上面的示例中,我們通過顯示的給出類型信息以實例化不同的模板類,這是因為模板類
 98         //的類型信息是無法像模板函數(shù)那樣可以通過函數(shù)參數(shù)進(jìn)行推演的,為了彌補(bǔ)這一缺失,我們可以
 99         //通過一個額外的模板函數(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.

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

 
 1     #include <stdio.h>
 2     #include <string.h>
 3     
 4     //1. 定義一個接口
 5     class BaseInterface {
 6     public:
 7         virtual ~BaseInterface() {}
 8         virtual void doPrint() = 0;
 9     };
10     
11     //2. 標(biāo)準(zhǔn)模板類繼承該接口,同時給出自己的doPrint()實現(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()實現(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. 對象創(chuàng)建輔助函數(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)用場景基本相同,因此下面的代碼將僅僅給出最基本的示例和注釋說明,以幫助大家熟悉他的語法即可:

 
 1     //1. 標(biāo)準(zhǔn)模板類。
 2     template<typename T1, typename T2>
 3     class MyClass {
 4         ... ...
 5     };
 6     //2. 兩個模板參數(shù)具有相同類型的部分特化類。
 7     template<typename T>
 8     class MyClass<T,T> {
 9         ... ...
10     }
11     //3. 第二個類型參數(shù)是int
12     template<typename T>
13     class MyClass<T,int> {
14         ... ...
15     }
16     //4. 兩個模板參數(shù)都是指針。
17     template<typename T1,typename T2>
18     class MyClass<T1*,T2*> {
19         ... ...
20     }
21     //5. 兩個模板參數(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ù)一樣,C++的模板也同樣支持缺省類型參數(shù)。

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

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

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

 
 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     };

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

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多