1.模板觀念與函數(shù)模板

項(xiàng)目地址

課程內(nèi)容

  • Part1 C++模板簡(jiǎn)介(An Introduction to C++ Template)
  • Part2 泛型編程(Generic Programming)
  • Part3 容器(Containers)
  • Part4 一些進(jìn)階問(wèn)題(Some Advanced Topic)

Part1 C++模板簡(jiǎn)介

  • C++模板概觀(Overview)
  • C++函數(shù)模板(Function Template)
  • C++類(lèi)模板(Class Template)
  • C++操作符重載(Operator Overloading)

C++模板概觀(1)

  • 模板(Templates)是C++的一種特性,允許函數(shù)或類(lèi)(對(duì)象)通過(guò)泛型(generic types)的形式表現(xiàn)或運(yùn)行
  • 模板可以使得函數(shù)或類(lèi)在對(duì)應(yīng)不同的型別(types)的時(shí)候正常工作,而無(wú)需為每一個(gè)型別都寫(xiě)一份代碼
  • 一個(gè)簡(jiǎn)單的例子:
  • 如果要寫(xiě)一個(gè)取兩個(gè)數(shù)中較大值的函數(shù)Max,在不使用模板的情況下,我們不得不針對(duì)不同的型別(比如int,long,char)提供每一種型別的重載:

int Max(int a, int b)
{
    return (a>b)?a:b;
}

long Max(long a, long b)
{
    return (a>b)?a:b;
}

char Max(char a, char b)
{
    return (a>b)?a:b;
}

C++模板概觀(2)

  • 一個(gè)簡(jiǎn)單的例子(續(xù))
  • 如果使用模板,則可以省去一堆亢余代碼,從而將函數(shù)原型縮減到非常簡(jiǎn)介的表達(dá):

template <typename T> T Max(T a, T b)
{
    return (a>b)?a:b;
}

  • C++主要有兩種類(lèi)型的模板:
  • 類(lèi)模版(Class template):使用泛型參數(shù)的類(lèi)(classes with generic parameters)
  • 函數(shù)模板(Function template):使用泛型參數(shù)的函數(shù)(functions with generic parameters)

C++模板概觀(3)

  • 模板實(shí)例化
  • 模板的聲明(declaration)其實(shí)并未給出一個(gè)函數(shù)或類(lèi)的完全定義(definition),只是提供了一個(gè)函數(shù)或類(lèi)的語(yǔ)法框架(syntactical skeletion)
  • 實(shí)例化是指從模板構(gòu)建出一個(gè)真正的函數(shù)或類(lèi)的過(guò)程,比如
    template <typename T> struct Object {...};
    可以用來(lái)構(gòu)建諸如Object<int>,Object<char>,Object<int>,Object<MyClass>等等不同型別的具體事例
  • 實(shí)例化有兩種類(lèi)型:
  • 顯式實(shí)例化-在代碼中明確指定要針對(duì)哪種型別進(jìn)行實(shí)例化
  • 隱式實(shí)例化-在首次使用時(shí)根據(jù)具體情況使用一種合適的型別進(jìn)行實(shí)例化

C++函數(shù)模板(1)

  • 什么是函數(shù)模板?
  • 函數(shù)模板是參數(shù)化的一族函數(shù)(a family of function)
  • 通過(guò)函數(shù)模板,可以定義一系列函數(shù),這些函數(shù)都基于同一套代碼,但是可以作用在不同型別的參數(shù)上

template <typename T>
inline T Max(
    const T& a,
    const T& b)
{
    return (a > b) ? a:b;
}

  • 定義函數(shù)模板
  • 定義一個(gè)函數(shù)模板,返回兩數(shù)中較大的那個(gè),該函數(shù)有兩個(gè)參數(shù):(a,b)
  • 參數(shù)型別未定,以模板參數(shù)T表示
  • 模板參數(shù)由關(guān)鍵typename引入

C++函數(shù)模板(2)

  • 定義函數(shù)模板(續(xù))
  • 也可以使用class替代typename來(lái)定義型別參數(shù)
    template <class T> inline T Max(const T& a, const T& b) {
    ...}
  • 從語(yǔ)法上講使用class和使用typename沒(méi)有區(qū)別
  • 但從語(yǔ)義上,class可能會(huì)導(dǎo)致誤區(qū),即只有類(lèi)才能作為型別參數(shù);而事實(shí)上T所表達(dá)的意思不僅僅只針對(duì)類(lèi),任何型別都可以
  • 請(qǐng)盡量使用typename!
  • class可以取代typename,但struct卻不可以,以下寫(xiě)法語(yǔ)法上是錯(cuò)誤的:
    //this is wrong!!!
    template <struct T> inline T Max(const T& a, const T& b)
    {
    ...
    }

C++函數(shù)模板(3)

  • 模板函數(shù)的使用
  • 調(diào)用Max,用int,float,以及std::wstring作為模板參數(shù)替換T
  • 對(duì)于不同的型別,都從模板實(shí)例化出不同的函數(shù)實(shí)體
  • 但是不可以使用不同型別的參數(shù)來(lái)調(diào)用Max,因?yàn)榫幾g器在編譯時(shí)已經(jīng)知道Max函數(shù)需要傳遞的型別

int i = 7, j = 30;
_tprintf(TEXT("Max(i,j) = %d\n"), Max(i,j));

double f = -1.8, g = -0.9;
_tprintf(TEXT("Max(f,g) = %f\n"), Max(f,g));

std::wstring s1 = TEXT("mathematics"), s2 = TEXT("math");
_tprintf(TEXT("Max(s1,s2) = %s\n"), Max(s1,s2).c_str());

Max(i,f);//compile error: template parameter 'T' is ambiguous  

C++函數(shù)模板(4)

  • 模板實(shí)例化
  • 用具體型別替代模板參數(shù)T的過(guò)程叫做實(shí)例化(instantiation);從而產(chǎn)生了一個(gè)模板事例
  • 一旦使用函數(shù)模板,這種實(shí)例化過(guò)程便由編譯器自動(dòng)觸發(fā)的,不需要額外去請(qǐng)求模板實(shí)例化
  • 如果實(shí)例化一種型別,而該型別內(nèi)部并不支持函數(shù)所使用的操作,那么就會(huì)導(dǎo)致一個(gè)編譯錯(cuò)誤,如下所示:
  • std::complex并沒(méi)有重載“>”,也就是說(shuō)改型別并不支持使用“>”比較大小,而Max函數(shù)使用“>”來(lái)判斷c1,c2的大小,所以無(wú)法通過(guò)Max(c1,c2)得到預(yù)期的結(jié)果
    std::complex<int> c1(1,2), c2(15,16); //編譯錯(cuò)誤!

C++函數(shù)模板(5)

  • 結(jié)論:模板被編譯了兩次
  1. 沒(méi)有實(shí)例化之前,檢查模板代碼本身是否有語(yǔ)法錯(cuò)誤
  2. 實(shí)例化期間,檢查對(duì)模板代碼的調(diào)用是否合法

C++函數(shù)模板(6)

  • 參數(shù)推導(dǎo)

  • 模板參數(shù)是有傳遞給模板函數(shù)的實(shí)參決定的

  • 不允許自動(dòng)型別轉(zhuǎn)換:每個(gè)T必須嚴(yán)格匹配!
    Max(1,2) //OK:兩個(gè)實(shí)參的型別都是int
    Max(1,2.0) //ERROR:第一個(gè)參數(shù)型別是int,第二個(gè)參數(shù)型別是double

    • 一般有兩種處理這種錯(cuò)誤的方法:
      1. 用static_cast或強(qiáng)制轉(zhuǎn)換參數(shù)型別以使兩者匹配
        Max(static_cast<double>(1), 2.0)
      2. 顯式指定T的型別
        Max<double>(1,2.0)

C++函數(shù)模板(7)

  • 函數(shù)模板重載
  • 函數(shù)模板也可以像普通函數(shù)一樣被重載
  • 非模板函數(shù)可以和同名的模板函數(shù)共存
  • 編譯器通過(guò)函數(shù)模板參數(shù)推導(dǎo)來(lái)決定使用調(diào)用哪個(gè)重載

//普通函數(shù)
//1
inline int const& Max(const int const& a, const int const& b)

//2
template <typename T>
inline T const& Max(const T const& a, const T const& b)

//3
template <typename T>
inline T const& Max(const T const& a, const T const& b, const T const& c)

C++函數(shù)模板(8)

函數(shù)模板重載(續(xù))

  • Max(7, 42, 68):調(diào)用接受三個(gè)參數(shù)的模板 ————3
  • Max(7.0, 42.0):調(diào)用Max<double> (參數(shù)推導(dǎo)) ————2
  • Max('a', 'b'):調(diào)用Max<char> (參數(shù)推導(dǎo)) ————2
  • Max(7, 42):調(diào)用非模板函數(shù),參數(shù)型別為int ————1 其他因素都相同的情況下,重載裁決過(guò)程調(diào)用非模板函數(shù),而不是從模板產(chǎn)生實(shí)例
  • Max<>(7, 42):調(diào)用Max<int> (參數(shù)推導(dǎo)) ————2 允許空模板參數(shù)列表
  • Max<double>(7, 42): 調(diào)用Max<double> (無(wú)需參數(shù)推導(dǎo)) ————2
  • Max('a', 42.7):調(diào)用非模版函數(shù),參數(shù)型別為int ————1 對(duì)于型別不同的 參數(shù)只能調(diào)用非模版函數(shù)(char型別'a'和double型別42.7都將轉(zhuǎn)化為int型別)

C++函數(shù)模板(9)

  • 總結(jié)
  • 對(duì)于不同的實(shí)參型別,模板函數(shù)定義了一族函數(shù)
  • 當(dāng)傳遞模板實(shí)參的時(shí)候,函數(shù)模板依據(jù)實(shí)參的型別進(jìn)行實(shí)例化
  • 可以顯式指定模板的實(shí)參型別
  • 函數(shù)模板可以重載
  • 當(dāng)重載函數(shù)模板時(shí),將改變限制在:顯式指定模板參數(shù)
  • 所有的重載版本的聲明必須位于它們被調(diào)用的位置之前
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,734評(píng)論 18 399
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,680評(píng)論 1 51
  • 第5章 引用類(lèi)型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類(lèi)型 使用基本類(lèi)型...
    大學(xué)一百閱讀 3,679評(píng)論 0 4
  • 重新系統(tǒng)學(xué)習(xí)下C++;但是還是少了好多知識(shí)點(diǎn);socket;unix;stl;boost等; C++ 教程 | 菜...
    kakukeme閱讀 20,456評(píng)論 0 50
  • 原文出自【CSDN】,轉(zhuǎn)載請(qǐng)保留原文鏈接: http://blog.csdn.net/love_gaohz/art...
    petit_prince閱讀 3,450評(píng)論 0 1

友情鏈接更多精彩內(nèi)容