1. 程式人生 > >C++總結之template

C++總結之template

# 函式模板 我們可以把函式模板當做一種特殊的函式,裡面的**引數型別可以是任意型別**,這樣的話我們就可以減少重複定義,從而讓這個函式模板自動適應不同的引數型別,也就是說函式可以適應多種型別的引數,例如`double`、`int`或者類什麼的。 C++為了實現上面的功能,引入了`template`這個概念。我們可以把template當成是一種特殊的型別引數,並且也可以在函式裡當做引數傳遞,心裡面把它當做`int`什麼的就行了。 **使用型別引數宣告函式模板的格式如下所示**: ``` template function_declaration; template function_declaration; // 這裡使用了typename 當做宣告型別引數 ``` 上面宣告函式模板的格式只有一處不同,那就是`class`和`typename`,在這裡其實使用哪一種都沒有區別,看自己喜歡就行,C++對此也沒有做嚴格的區分; 為了更好的說明如何使用函式模板,便在舉一個很形象的例子,那就是一個用來返回較大值的函式,具體寫法如下所示: ``` template T GetMax(T a, T b) return a > b ? a : b; ``` 在上面的短短几行程式碼中我們就建立了一個函式模板用來獲取兩個數之間較大的那個數,不難看出T在這裡並沒有指明具體的型別,在這我們仍然可以在心裡把它當做普通變數處理,返回值也是T。 為了使用我們定義的函式模板,可以參照統一的函式模板呼叫格式: ``` function_name (parameters); // type就是具體的型別,例如int、double這些,parameters就是函式裡的引數,也是具體型別 ``` 所以,如果我們想要實現獲取兩個整形值裡較大的那個,我們可以傳入int這個型別之後呼叫`GetMax`函式,具體示例如下: ``` int x = 4; int y = 2; int max = GetMax (x, y); // max = 4 ``` # 類模板 由於template宣告的型別可以是**任意型別**,也就是使用的時候傳入具體的型別就行。所以可以參考上面函式模板的例子構造類模板也是一樣的,在使用這個類的時候傳入具體的變數型別就行了。例如下面的類模板定義: ``` template class MyPair{ T value[2]; public: MyPair(T first, T second) { value[0] = first; value[1] = second; } }; ``` 類模板的示例程式碼中定義一個`MyPair`類,**用來儲存任意型別的兩個元素**,例如`double`,`char`,`int`等,下面我就給出兩個示例,分別儲存`double`和`int`型別的變數 ``` MyPair myInt(2, 3); // 儲存兩個整型值 MyPair myDouble(2.3, 3.43); // 儲存兩個double值 ``` 模板類的成員函式也可以在**類外定義**,寫法和函式模板的寫法是一樣的,具體示例如下所示: ``` template class MyPair { T a, b; public: mypair (T first, T second) {a=first; b=second;} T Getmax (); }; template T MyPair::Getmax () // 在類外定義函式, 注意前面的寫法和函式模板寫法一致 { T retval; retval = a>b? a : b; return retval; } ``` # 模板特化 如果我們想要為類模板定義一個不同的實現介面,並且要求需要將特定引數作為引數傳遞時,那麼我們就可以將該**模板特化**; 為了更好地說明模板特化,還是舉個簡單的例子吧。假設我們定義一個類`mycontainer`,這個類可以儲存一個任意型別的變數,並且這個類還有一個函式叫做`increasement`用來將儲存的型別加一。並且,如果這個類儲存的是一個char型別的時候,我們會發現這個類對於實現將其中的成員變數轉換為大寫的功能將更加方便,不妨將這個函式定義為`ToUpper`,因此,我們可以為char型別的類模板實現模板特化,具體的示例程式碼如下: ``` // 模板特化 #include using namespace std; // 宣告類模板: template class mycontainer { T element; public: mycontainer (T arg) {element=arg;} T increase () {return ++element;} }; // char型別的模板特化: template <> class mycontainer { char element; public: mycontainer(char arg) {element=arg;} char ToUpper() { if ((element>='a')&&(element<='z')) element+='A'-'a'; return element; } }; ``` 對於上面的模板特化,我們需要幾點,注意類模板和模板特化的**區別和聯絡**: * 在類模板的前面加上`template <>`,這表明是模板特化,也就是是說模板特化都需要加上這句話; * 還有一點就是類模板後面使用了``引數,這個特定引數表示我們將模板類特化程``型別; # template的其他用法 除了以`template`或者`class`關鍵字開頭宣告的表示型別的模板引數之外,template也可以具有其他型別的引數,例如`int`、`double`這些引數,就類似於一個函式中擁有多個引數,每個引數型別還不一樣。為了更好的說明`template`的其他用法,不妨參考下面的示例程式碼, ``` #include using namespace std; template // 這裡除了含有class宣告的型別之外,還擁有一個int型別 class mysequence { T memblock [N]; public: void setmember(int x, T value); T getmember(int x); }; template void mysequence::setmember(int x, T value) { memblock[x]=value; } template T mysequence::getmember(int x) { return memblock[x]; } int main(){ mysequence myints; mysequence myfloats; myints.setmember(0,100); myfloats.setmember(3,3.1416); cout << myints.getmember(0) << '\n'; cout << myfloats.getmember(3) << '\n'; return 0