日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網(wǎng)站首頁 編程語言 正文

C語言的模板與泛型編程你了解嗎_C 語言

作者:日天少年wzh ? 更新時間: 2022-06-02 編程語言

模板與泛型編程淺談

摘要(Effective C++):

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

模板與泛型編程簡單介紹

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

? 我們所常用的STL標準庫中,每一個容器都提供了單一的,泛型的定義,例如我們所常用的vector,我們可以定義很多類型的vector

vector<int> vi; // vi是裝載int類型的vector容器的實例
vector<string> vs; // vs是裝載string類型的vector容器的實例
vector<double> vd; // vd是裝載double類型的vector容器的實例

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

函數(shù)模板

// 簡單的比較函數(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開始,后跟一個模板參數(shù)列表,這是一個逗號分隔的一個或多個模板參數(shù)的列表,用尖括號包圍起來

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

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

簡單了解模板的實例化過程

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

? 當我們調(diào)用一個函數(shù)模板的時候,編譯器(通常)用函數(shù)實參來為我們推斷模板實參。簡單來講,便是我們在調(diào)用函數(shù)模板的時候,編譯器通過使用實參的類型來確定綁定到模板參數(shù)T的類型

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

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

簡單來說,編譯器用推斷出的模板參數(shù)來為我們實例化一個特定版本的函數(shù)

模板編譯

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

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

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

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

大多數(shù)編譯錯誤出現(xiàn)的時機?

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

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

類模板

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

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

定義類模板

template<typename T>
class T_vector {
public:
	typedef T value_type;
    // 構(gòu)造函數(shù)
    T_vector() =default;
    T_vectot(std::initializer_list<T> il);
    // 容器的元素數(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]無效,則拋出msg
    void check(size_type i,const std::string &msg) const;
}

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

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

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

類模板成員函數(shù)的實例化

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

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

如果一個成員函數(shù)沒有被使用,則它將不會被實例化

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

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

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

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

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

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

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

注意事項:

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

類模板部分特例化

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

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

總結(jié)

原文鏈接:https://blog.csdn.net/weixin_51958878/article/details/123852228

欄目分類
最近更新