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