最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言的模板與泛型編程你了解嗎

 更新時(shí)間:2022年03月31日 13:07:32   作者:日天少年wzh  
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的模板與泛型編程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

模板與泛型編程淺談

摘要(Effective C++):

? C++template的最初發(fā)展動(dòng)機(jī)很直接:讓我們得以建立“類(lèi)型安全”的容器如vector,list和map。然而當(dāng)愈多人用上templates時(shí),他們發(fā)現(xiàn)template有能力完成愈多可能的變化。容器當(dāng)然很好,但泛型編程(generic programming)——寫(xiě)出的代碼和其所處理的對(duì)象類(lèi)型彼此獨(dú)立——更好。STL算法如for_each,find和merge就是這一類(lèi)編程的結(jié)果。最終人們發(fā)現(xiàn),C++template機(jī)制自身是一部完整的圖靈機(jī):它可以用來(lái)計(jì)算任何可計(jì)算的值。于是導(dǎo)出了模板元編程(template mataprogramming),創(chuàng)造出“在C++編譯器內(nèi)執(zhí)行并于編譯完成時(shí)停止執(zhí)行”的程序。

模板與泛型編程簡(jiǎn)單介紹

? 面向?qū)ο缶幊蹋∣OP)和泛型編程都可以處理編寫(xiě)程序時(shí)不知道類(lèi)型的情況;二者的不同之處在于:OOP能處理類(lèi)型在程序運(yùn)行之前都未知的情況;而在泛型編程中,在編譯時(shí)就能獲知類(lèi)型了

? 我們所常用的STL標(biāo)準(zhǔn)庫(kù)中,每一個(gè)容器都提供了單一的,泛型的定義,例如我們所常用的vector,我們可以定義很多類(lèi)型的vector

vector<int> vi; // vi是裝載int類(lèi)型的vector容器的實(shí)例
vector<string> vs; // vs是裝載string類(lèi)型的vector容器的實(shí)例
vector<double> vd; // vd是裝載double類(lèi)型的vector容器的實(shí)例

模板是泛型編程的基礎(chǔ),一個(gè)模板就是一個(gè)創(chuàng)建類(lèi)或者函數(shù)的藍(lán)圖或者公式

函數(shù)模板

// 簡(jiǎn)單的比較函數(shù)模板
template<typename T>
int cmp(const T& v1,const T& v2) {
    if(v1<v2)
        return -1;
    else if(v1>v2)
        return 1;
    else
        return 0;
}

函數(shù)定義以關(guān)鍵字template開(kāi)始,后跟一個(gè)模板參數(shù)列表,這是一個(gè)逗號(hào)分隔的一個(gè)或多個(gè)模板參數(shù)的列表,用尖括號(hào)包圍起來(lái)

**注:**在模板定義中,模板參數(shù)列表不能為空

模板參數(shù)列表表示在類(lèi)或函數(shù)定義中用到的類(lèi)型或者值。當(dāng)我們使用模板的時(shí)候,我們可以(顯式或隱式地)指定模板實(shí)參,將其綁定到模板參數(shù)上

簡(jiǎn)單了解模板的實(shí)例化過(guò)程

? 眾所周知,當(dāng)你覺(jué)得模板編程十分智能的時(shí)候,一定是有東西在為你負(fù)重前行,C++提供了模板與泛型編程的這個(gè)能力,這便意味著有一個(gè)東西在為你動(dòng)態(tài)地實(shí)現(xiàn)模板的功能,而這一定是比C++這個(gè)高級(jí)語(yǔ)言層面更為底層的東西,而我們所了解的知識(shí)中,比C++高級(jí)語(yǔ)言較為底層的東西,除了操作系統(tǒng),便是編譯器了。

? 當(dāng)我們調(diào)用一個(gè)函數(shù)模板的時(shí)候,編譯器(通常)用函數(shù)實(shí)參來(lái)為我們推斷模板實(shí)參。簡(jiǎn)單來(lái)講,便是我們?cè)谡{(diào)用函數(shù)模板的時(shí)候,編譯器通過(guò)使用實(shí)參的類(lèi)型來(lái)確定綁定到模板參數(shù)T的類(lèi)型

cout<<cmp(1,0)<<endl; // T為int

在上訴代碼中,函數(shù)cmp的實(shí)參類(lèi)型是int,編譯器便會(huì)推斷出模板實(shí)參為int,并將它綁定到模板參數(shù)T上

簡(jiǎn)單來(lái)說(shuō),編譯器用推斷出的模板參數(shù)來(lái)為我們實(shí)例化一個(gè)特定版本的函數(shù)

模板編譯

當(dāng)編譯器遇到一個(gè)模板定義的時(shí)候,它并不會(huì)生成代碼。只有我們實(shí)例化出模板的一個(gè)特定的版本時(shí),編譯器才會(huì)生成其對(duì)應(yīng)的代碼。當(dāng)我們使用(而不是定義)模板時(shí),編譯器才會(huì)生成代碼。這個(gè)特性影響我們?nèi)绾谓M織代碼以及錯(cuò)誤何時(shí)才可以被檢測(cè)到

通常來(lái)說(shuō),我們將類(lèi)定義和函數(shù)說(shuō)明放在頭文件中,而普通函數(shù)和類(lèi)的成員函數(shù)的定義放在源文件中

模板則不盡相同:為了生成一個(gè)實(shí)例化的版本,編譯器需要掌握函數(shù)模板或類(lèi)模板成員函數(shù)的定義

總結(jié)與非模板代碼不同,模板的頭文件通常既包括聲明也包括定義,即函數(shù)模板和類(lèi)模板成員函數(shù)的定義通常放在頭文件中

大多數(shù)編譯錯(cuò)誤出現(xiàn)的時(shí)機(jī) 

  • 第一階段,編譯模板本身時(shí),該時(shí)期所出現(xiàn)的錯(cuò)誤大多數(shù)為語(yǔ)法錯(cuò)誤
  • 第二階段,編譯器遇到模板使用時(shí)
  • 第三階段,模板實(shí)例化時(shí),而只有在這個(gè)階段才能發(fā)現(xiàn)類(lèi)型相關(guān)的問(wèn)題

**注意事項(xiàng):**保證傳遞給模板的實(shí)參支持模板所要求的操作,以及這些操作在模板中能正確的工作,是調(diào)用者的責(zé)任

類(lèi)模板

類(lèi)模板是用來(lái)生成類(lèi)的藍(lán)圖的。與函數(shù)模板不同之處是,編譯器不能為類(lèi)模板推斷模板參數(shù)類(lèi)型。 所以我們必須在模板名后的尖括號(hào)中提供額外的信息——用來(lái)替代模板參數(shù)的模板實(shí)參列表

vector<int> vi;
deque<double> dd;
pair<string,int> key_val;

定義類(lèi)模板

template<typename T>
class T_vector {
public:
	typedef T value_type;
    // 構(gòu)造函數(shù)
    T_vector() =default;
    T_vectot(std::initializer_list<T> il);
    // 容器的元素?cái)?shù)目
    size_type size() const { return data->size(); }
    bool empty() const { return data->empty(); }
    // 添加元素
    void push_back(const T& val) { 
        data->push_back(val);
    }
    void push_back(T &&val) {
        data->push_back(std::move(val));
    }
private:
    std::shared_ptr<std::vector<T> > data;
    // 若data[i]無(wú)效,則拋出msg
    void check(size_type i,const std::string &msg) const;
}

類(lèi)似函數(shù)模板,類(lèi)模板以關(guān)鍵字template開(kāi)始,后跟模板參數(shù)列表。在類(lèi)模板(及其成員)的定義中,我們將模板參數(shù)當(dāng)作替身,代替使用模板時(shí)用戶(hù)需要提供的類(lèi)型或值

**注:**一個(gè)類(lèi)模板的每一個(gè)實(shí)例都形成一個(gè)獨(dú)立的類(lèi),而類(lèi)模板的每個(gè)實(shí)例都有其自己版本的成員函數(shù)

? 所以,我們可能會(huì)出現(xiàn)一個(gè)單一模板并不能滿足所有類(lèi)型的需求,而模板特例化就出現(xiàn)了

類(lèi)模板成員函數(shù)的實(shí)例化

? 默認(rèn)的情況下,一個(gè)類(lèi)模板的成員函數(shù)只有在程序用到它的時(shí)候才會(huì)實(shí)例化

// 實(shí)例化T_vector和接受initializer_list<int>的構(gòu)造函數(shù)
T_vector<int> T_vi = { 0,1,2,3,4,5 };

如果一個(gè)成員函數(shù)沒(méi)有被使用,則它將不會(huì)被實(shí)例化

為什么我們需要模板特例化?

當(dāng)我們編寫(xiě)單一的模板時(shí),使其對(duì)任何可能的模板實(shí)參都是最合適的,都能實(shí)例化,但者往往都是過(guò)于理想化的情況。在某些特殊的情況下,通用的模板的定義可能對(duì)特定的類(lèi)型是不合適的,通用定義的模板可能會(huì)出現(xiàn)編譯失敗或者做得不夠完善的情況。

故,當(dāng)我們不能(或者不希望)使用模板版本的時(shí)候,可以定義類(lèi)或函數(shù)模板的一個(gè)特例化版本

定義函數(shù)模板特例化

// 原先cmp函數(shù)的特殊版本,用來(lái)處理特殊的字符數(shù)組的指針template<>int cmp(const char* const& p1,const char* const& p2) {    return strcmp(p1,p2);}// 原先cmp函數(shù)的特殊版本,用來(lái)處理特殊的字符數(shù)組的指針
template<>
int cmp(const char* const& p1,const char* const& p2) {
    return strcmp(p1,p2);
}

函數(shù)重載與模板特例化的區(qū)別

? 當(dāng)定義函數(shù)模板的特例化版本時(shí),我們本質(zhì)上接管了編譯器的工作。即,我們?yōu)樵鹊哪0宓钠渲幸粋€(gè)特殊的實(shí)例提供了定義。簡(jiǎn)而言之,特例化的本質(zhì)是實(shí)例化一個(gè)模板,而非重載它,因此特例化并不影響函數(shù)匹配

注意事項(xiàng):

  • 為了特例化一個(gè)模板,原模版的聲明必須在作用域中
  • 在任何使用模板實(shí)例的代碼之前,特例化版本的聲明也必須在作用域中
  • 所有同名模板的聲明應(yīng)該放在前面,然后是這些模板的特例化版本

類(lèi)模板部分特例化

與函數(shù)模板不同的是,類(lèi)模板的特例化不必為所有模板參數(shù)提供實(shí)參。一個(gè)類(lèi)模板的部分特例化本身是一個(gè)模板,使用它時(shí)用戶(hù)還必須為那些在特例化版本中指定的模板參數(shù)提供實(shí)參

我們只能部分特例化類(lèi)模板,而不能部分特例化函數(shù)模板

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • C++設(shè)計(jì)模式之建造者模式

    C++設(shè)計(jì)模式之建造者模式

    這篇文章主要介紹了C++設(shè)計(jì)模式之建造者模式,一個(gè)復(fù)雜對(duì)象是由多個(gè)部件組成的,建造者模式是把復(fù)雜對(duì)象的創(chuàng)建和部件的創(chuàng)建分別開(kāi)來(lái),分別用Builder類(lèi)和Director類(lèi)來(lái)表示,需要的朋友可以參考下
    2014-09-09
  • OpenCV實(shí)現(xiàn)幀差法檢測(cè)運(yùn)動(dòng)目標(biāo)

    OpenCV實(shí)現(xiàn)幀差法檢測(cè)運(yùn)動(dòng)目標(biāo)

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)幀差法檢測(cè)運(yùn)動(dòng)目標(biāo),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C語(yǔ)言掃雷排雷小游戲?qū)崿F(xiàn)全程

    C語(yǔ)言掃雷排雷小游戲?qū)崿F(xiàn)全程

    本篇我將帶領(lǐng)大家攻克掃雷游戲各處難點(diǎn),讓你寫(xiě)掃雷不在困難,我們的掃雷游戲可以實(shí)現(xiàn)標(biāo)記雷的功能和展開(kāi)一片的功能。我們將分三個(gè)文件為大家介紹,分別為test.c,game.h和game.c
    2022-05-05
  • C語(yǔ)言基于EasyX實(shí)現(xiàn)貪吃蛇

    C語(yǔ)言基于EasyX實(shí)現(xiàn)貪吃蛇

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言基于EasyX實(shí)現(xiàn)貪吃蛇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++字符串拼接效率對(duì)比(+=、append、stringstream、sprintf)

    C++字符串拼接效率對(duì)比(+=、append、stringstream、sprintf)

    這篇文章主要介紹了C++字符串拼接效率對(duì)比(+=、append、stringstream、sprintf),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • C++?typedef常見(jiàn)用法詳解

    C++?typedef常見(jiàn)用法詳解

    這篇文章主要介紹了C++?typedef用法詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • C語(yǔ)言編寫(xiě)一個(gè)鏈表

    C語(yǔ)言編寫(xiě)一個(gè)鏈表

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言編寫(xiě)一個(gè)鏈表,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • C語(yǔ)言用函數(shù)實(shí)現(xiàn)電話簿管理系統(tǒng)

    C語(yǔ)言用函數(shù)實(shí)現(xiàn)電話簿管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言用函數(shù)實(shí)現(xiàn)電話簿管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++繼承的賦值轉(zhuǎn)換與菱形虛擬繼承深入詳解

    C++繼承的賦值轉(zhuǎn)換與菱形虛擬繼承深入詳解

    今天我要給大家介紹C++中更深入的內(nèi)容了,C++繼承的賦值轉(zhuǎn)換與菱形虛擬繼承。C++這門(mén)語(yǔ)言為了使代碼不冗余,做了些什么操作呢?C++的繼承就很好地實(shí)現(xiàn)了類(lèi)層次的代碼復(fù)用,今天我就要來(lái)和大家好好聊一聊它了
    2022-08-08
  • 簡(jiǎn)單實(shí)現(xiàn)C語(yǔ)言2048游戲

    簡(jiǎn)單實(shí)現(xiàn)C語(yǔ)言2048游戲

    這篇文章主要為大家詳細(xì)介紹了簡(jiǎn)單實(shí)現(xiàn)C語(yǔ)言2048游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05

最新評(píng)論

广丰县| 满洲里市| 兴城市| 新余市| 临城县| 比如县| 克拉玛依市| 南靖县| 焦作市| 巴林左旗| 松潘县| 锡林浩特市| 安岳县| 家居| 潢川县| 桂林市| 洱源县| 天等县| 连南| 温泉县| 许昌县| 宿松县| 银川市| 桐柏县| 宜君县| 金溪县| 连江县| 乌鲁木齐县| 乐平市| 界首市| 宝清县| 囊谦县| 金门县| 巴林左旗| 清丰县| 巍山| 静安区| 斗六市| 巩义市| 鹤峰县| 定日县|