C++ 模版 學習總結(jié)


C++ 模版

模板是C++支持參數(shù)化多態(tài)的工具方庭,使用模板可以使用戶為類或者函數(shù)聲明一種一般模式翩瓜,使得類中的某些數(shù)據(jù)成員或者成員函數(shù)的參數(shù)跨扮、返回值取得任意類型序无;模板是一種對類型進行參數(shù)化的工具。
  通常有兩種形式:函數(shù)模板和類模板衡创;
  函數(shù)模板:針對僅參數(shù)類型不同的函數(shù)帝嗡;
  類模板: 針對僅數(shù)據(jù)成員和成員函數(shù)類型不同的類。
注意:模板的聲明或定義只能在全局璃氢,命名空間或類范圍內(nèi)進行丈探。即不能在局部范圍內(nèi)進行。

1拔莱、 函數(shù)模版

 template <class 形參名碗降,class 形參名,......> 返回類型 函數(shù)名(參數(shù)列表)
 {
            函數(shù)體
 }

1塘秦、其中template和class是關見字讼渊,class可以用typename 關見字代替,在這里typename 和class沒區(qū)別,這里說名一下兩個的區(qū)別和相同:
--- 在聲明 template parameters(模板參數(shù))時尊剔,class 和 typename 是可互換的爪幻。
--- 用 typename 去標識 nested dependent type names(嵌套依賴類型名),在 base class lists(基類列表)中或在一個 member initialization list(成員初始化列表)中作為一個 base class identifier(基類標識符)時除外,這種情況 class 和 typename是不可互換挨稿。
看看例子:

class MyArray 
{ 
public:
typedef int LengthType;
.....
}

template<class T>
void MyMethod( T myarr ) 
{ 
typedef typename T::LengthType LengthType; 
LengthType length = myarr.GetLength; 
}

這個時候typename的作用就是告訴c++編譯器仇轻,typename后面的字符串為一個類型名稱,而不是成員函數(shù)或者成員變量奶甘,這個時候如果前面沒有
typename篷店,編譯器沒有任何辦法知道T::LengthType是一個類型還是一個成員名稱(靜態(tài)數(shù)據(jù)成員或者靜態(tài)函數(shù)),所以編譯不能夠通過臭家。
2疲陕、 <>括號中的參數(shù)叫模板形參
模板形參和函數(shù)形參很相像,模板形參一般不能為空钉赁。為空的時候后面需要具解釋這個用法特化處理蹄殃。這里我們先介紹不為空的。
一但聲明了模板函數(shù)就可以用模板函數(shù)的形參名聲明類中的成員變量和成員函數(shù)你踩,即可以在該函數(shù)中使用內(nèi)置類型的地方都可以使用模板形參名诅岩。模板形參需要調(diào)用該模板函數(shù)時提供的模板實參來初始化模板形參,一旦編譯器確定了實際的模板實參類型就稱他實例化了函數(shù)模板的一個實例带膜。

注意:對于函數(shù)模板而言不存在 h(int,int) 這樣的調(diào)用吩谦,不能在函數(shù)調(diào)用的參數(shù)中指定模板形參的類型,對函數(shù)模板的調(diào)用應使用實參推演來進行钱慢,即只能進行 h(2,3) 這樣的調(diào)用逮京,或者int a, b; h(a,b)。
示例:

template <class T>
int compare(const T &left, const T&right)
{
    std::cout <<"in template<class T>..." <<std::endl;
    return (left - right);
}

2束莫、 類模版

template<class  形參名懒棉,class 形參名,…>   class 類名     // 定義
{ ... };

類模板對象的創(chuàng)建:比如一個模板類A览绿,則使用類模板創(chuàng)建對象的方法為A<int> m;
對于類模板策严,模板形參的類型必須在類名后的尖括號中明確指定。比如A<2> m;用這種方法把模板形參設置為int是錯誤的饿敲。
在類模板外部定義成員函數(shù)的方法為:
    template<模板形參列表> 函數(shù)返回類型 類名<模板形參名>::函數(shù)名(參數(shù)列表){函數(shù)體}妻导,
比如有兩個模板形參T1,T2的類A中含有一個void h()函數(shù)怀各,則定義該函數(shù)的語法為:

    template<class T1,class T2> void A<T1,T2>::h(){}

注意:當在類外面定義類的成員時template后面的模板形參應與要定義的類的模板形參一致倔韭。
示例:

#include <iostream>
#include <cstring>
#include <cmath>
// general version
template<class T>
class Compare
{
public:
    static bool IsEqual(const T& lh, const T& rh)
    {
        std::cout <<"in the general class..." <<std::endl;
        return lh == rh;
    }
};

3、 模版形參

有三種類型的模板形參:‘類型’形參瓢对,非類型形參和模板形參寿酌。類型不是指class定義的類,通過模版定義的<typename T>這些硕蛹。

1醇疼、類型形參
類型模板形參:類型形參由關見字class或typename后接說明符構(gòu)成硕并,如template<class T> void h(T a){};其中T就是一個類型形參,類型形參的名字由用戶自已確定秧荆。模板形參表示的是一個未知的類型倔毙。
注意:
對于函數(shù)模版:不能為同一個模板類型形參指定兩種不同的類型,比如template<class T>void h(T a, T b){}乙濒,語句調(diào)用h(2, 3.2)將出錯陕赃。
對于類模版:聲明類對象為:A<int> a,比如template<class T>T g(T a, T b){}琉兜,語句調(diào)用a.g(2, 3.2)在編譯時不會出錯凯正,有警告毙玻;當聲明A<double> a,警告都不會有豌蟋。

2、 非類型形參
1 桑滩、非類型模板形參:模板的非類型形參也就是內(nèi)置類型形參梧疲,如template<class T, int a> class B{};其中int a就是非類型的模板形參。
2运准、 非類型形參在模板定義的內(nèi)部是常量值幌氮。
3、 非類型模板的形參只能是整型胁澳,指針和引用该互。
4、 調(diào)用非類型模板形參的實參必須是一個常量表達式韭畸,即他必須能在編譯時計算出結(jié)果宇智。常量表達式有:
---1> 全局變量的地址或引用,全局對象的地址或引用const類型變量是常量表達式胰丁,可以用作非類型模板形參的實參随橘。
---2> sizeof表達式的結(jié)果是一個常量表達式,也能用作非類型模板形參的實參锦庸。

5机蔗、當模板的形參是整型時調(diào)用該模板時的實參必須是整型的,且在編譯期間是常量甘萧,比如template <class T, int a> class A{};如果有int b萝嘁,這時A<int, b> m;將出錯,因為b不是常量扬卷,如果const int b牙言,這時A<int, b> m;就是正確的,因為這時b是常量邀泉。

6嬉挡、非類型形參一般不應用于函數(shù)模板中钝鸽,比如有函數(shù)模板template<class T, int a> void h(T b){},若使用h(2)調(diào)用會出現(xiàn)無法為非類型形參a推演出參數(shù)的錯誤庞钢,對這種模板函數(shù)可以用顯示模板實參來解決拔恰,如用h<int, 3>(2)這樣就把非類型形參a設置為整數(shù)3。顯示模板實參在后面介紹基括。
7颜懊、 非類型模板形參的形參和實參間所允許的轉(zhuǎn)換
  1、允許從數(shù)組到指針风皿,從函數(shù)到指針的轉(zhuǎn)換河爹。如:template <int *a> class A{}; int c[1]; A<c> m;即數(shù)組到指針的轉(zhuǎn)換
  2、const修飾符的轉(zhuǎn)換桐款。如:template<const int *a> class A{}; int b; A<&b> m; 即從int *到const int *的轉(zhuǎn)換咸这。
  3、提升轉(zhuǎn)換魔眨。如:template<int a> class A{}; const short c=2; A<c> m; 即從short到int 的提升轉(zhuǎn)換
  4媳维、整值轉(zhuǎn)換。如:template<unsigned int a> class A{}; A<3> m; 即從int 到unsigned int的轉(zhuǎn)換遏暴。
  5侄刽、常規(guī)轉(zhuǎn)換。
注意: 任何局部對象朋凉,局部變量州丹,局部對象的地址,局部變量的地址都不是一個常量表達式杂彭,都不能用作非類型模板形參的實參墓毒。全局指針類型,全局變量盖灸,全局對象也不是一個常量表達式蚁鳖,不能用作非類型模板形參的實參。

補充:
類模板的默認模板類型形參:
1赁炎、可以為類模板的類型形參提供默認值醉箕,但不能為函數(shù)模板的類型形參提供默認值。函數(shù)模板和類模板都可以為模板的非類型形參提供默認值徙垫。
2讥裤、類模板的類型形參默認值形式為:template<class T1, class T2=int> class A{};為第二個模板類型形參T2提供int型的默認值。
3姻报、類模板類型形參默認值和函數(shù)的默認參數(shù)一樣己英,默認應該在后面,如果第一個設置默認吴旋,那么后面其他的都應該設置默認损肛。
4厢破、 在類模板的外部定義類中的成員時template 后的形參表應省略默認的形參類型。如: template<class T1, class T2=int> class A{public: void h();}; 外部函數(shù) :template<class T1,class T2> void A<T1,T2>::h(){}治拿。

4摩泪、 模版特化

特化:為已有的模板參數(shù)進行一些使其特殊化的指定,使得以前不受任何約束的模板參數(shù)劫谅,或受到特定的修飾(例如const或者變成為了指針之類见坑,甚至是經(jīng)過別的模板類包裝之后的模板類型)或完全被指定了下來。

分類:
------- 針對特化的對象不同捏检,分為兩類:函數(shù)模板的特化和類模板的特化荞驴。
函數(shù)模板的特化:當函數(shù)模板需要對某些類型進行特化處理,稱為函數(shù)模板的特化贯城。
類模板的特化:當類模板內(nèi)需要對某些類型進行特別處理時熊楼,使用類模板的特化。
------- 特化整體上分為全特化和偏特化
全特化:全特化的類中的函數(shù)可以與模板類不一樣冤狡。
偏特化:就是模板中的模板參數(shù)沒有被全部確定孙蒙,需要編譯器在編譯時進行確定项棠。

注意: 模板函數(shù)只能全特化悲雳,沒有偏特化(以后可能有);模板類是可以全特化和偏特化的香追。

還是使用上面的示例:

// 一個模版函數(shù)
template <class T>
int compare(const T &left, const T&right)
{
    std::cout <<"in template<class T>..." <<std::endl;
    return (left - right);
}

// 一個特化的函數(shù)
template < >
int compare<const char*>(const char* left, const char* right)
{
    std::cout <<"in special template< >..." <<std::endl;

    return strcmp(left, right);
}

// 或者
template < >
int compare(const char* left, const char* right)
{
    std::cout <<"in special template< >..." <<std::endl;

    return strcmp(left, right);
}

函數(shù)模版的特化合瓢,當函數(shù)調(diào)用發(fā)現(xiàn)有特化后的匹配函數(shù)時,會優(yōu)先調(diào)用特化的函數(shù)透典,而不再通過函數(shù)模版來進行實例化晴楔。

類模板的特化:與函數(shù)模板類似,當類模板內(nèi)需要對某些類型進行特別處理時峭咒,使用類模板的特化税弃。
類模板特化的幾種類型:一是特化為絕對類型;二是特化為引用凑队,指針類型则果;三是特化為另外一個類模板。

示例:

// 1漩氨、   特化為絕對類型
template<class T>
class Compare
{
public:
    static bool IsEqual(const T& lh, const T& rh)
    {
        std::cout <<"in the general class..." <<std::endl;
        return lh == rh;
    }
};
// 特化為 float類型
template<>
class Compare<float>
{
public:
    static bool IsEqual(const float& lh, const float& rh)
    {
        std::cout <<"in the float special class..." <<std::endl;

        return std::abs(lh - rh) < 10e-3;
    }
};

// 2 西壮、 特化為指針或者引用類型
// 特化為T*指針
template<class T>
class Compare<T*>
{
public:
    static bool IsEqual(const T* lh, const T* rh)
    {
        return Compare<T>::IsEqual(*lh, *rh);
    }
};
// 除了T*, 我們也可以將T特化為 const T*, T&, const T&。

// 3叫惊、 特化為另外一個類模板
// 特化 任何其他的模版
template <class T1> 
struct SpecializedType
{
    T1 x1;
    T1 x2;
};
template <class T>
class Compare<SpecializedType<T> >
{
public:
    static bool IsEqual(const SpecializedType<T>& lh, const SpecializedType<T>& rh)
    {
        return Compare<T>::IsEqual(lh.x1 + lh.x2, rh.x1 + rh.x2);
    }
};

模版總結(jié)基本這么多?钋唷!霍狰!

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抡草,一起剝皮案震驚了整個濱河市饰及,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌康震,老刑警劉巖旋炒,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異签杈,居然都是意外死亡瘫镇,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門答姥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铣除,“玉大人,你說我怎么就攤上這事鹦付∩姓常” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵敲长,是天一觀的道長郎嫁。 經(jīng)常有香客問我,道長祈噪,這世上最難降的妖魔是什么泽铛? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮辑鲤,結(jié)果婚禮上盔腔,老公的妹妹穿的比我還像新娘。我一直安慰自己月褥,他們只是感情好弛随,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宁赤,像睡著了一般舀透。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上决左,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天愕够,我揣著相機與錄音,去河邊找鬼哆窿。 笑死链烈,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的挚躯。 我是一名探鬼主播强衡,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼码荔!你這毒婦竟也來了漩勤?” 一聲冷哼從身側(cè)響起感挥,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎越败,沒想到半個月后触幼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡究飞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年置谦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亿傅。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡媒峡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出葵擎,到底是詐尸還是另有隱情谅阿,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布酬滤,位于F島的核電站签餐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏盯串。R本人自食惡果不足惜氯檐,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嘴脾。 院中可真熱鬧男摧,春花似錦、人聲如沸译打。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奏司。三九已至,卻和暖如春樟插,著一層夾襖步出監(jiān)牢的瞬間韵洋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工黄锤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留搪缨,地道東北人。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓鸵熟,卻偏偏與公主長得像副编,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子流强,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容

  • C++ 模板簡介 一痹届、模板 使用模板的目的就是能夠讓程序員編寫與類型無關的代碼呻待。 模板是一種對類型進行參數(shù)化的工具...
    MinoyJet閱讀 2,360評論 0 12
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,513評論 1 51
  • 挫折往往就是轉(zhuǎn)折的開始,不要抱怨環(huán)境更不要抱怨自己队腐。 世界沒權利為你負責蚕捉,能對你負責只能是你自己。抱怨世界你...
    學海無涯宇少閱讀 369評論 0 0