C++之類模板詳解(一)
阿新 • • 發佈:2018-12-30
C++ 除了支援函式模板,還支援類模板(Class Template)。函式模板中定義的型別引數可以用在函式宣告和函式定義中,類模板中定義的型別引數可以用在類宣告和類實現中。類模板的目的同樣是將資料的型別引數化。
宣告類模板的語法為:
一但聲明瞭類模板,就可以將型別引數用於類的成員函式和成員變量了。換句話說,原來使用 int、float、char 等內建型別的地方,都可以用型別引數來代替。
假如我們現在要定義一個類來表示座標,要求座標的資料型別可以是整數、小數和字串,例如:
這個時候就可以使用類模板,請看下面的程式碼:
第一行是模板頭,第二行是函式頭,它們可以合併到一行,不過為了讓程式碼格式更加清晰,一般是將它們分成兩行。
下面就對 Point 類的成員函式進行定義:
除了物件變數,我們也可以使用物件指標的方式來例項化:
x=10, y=20
x=10, y=東京180度
x=東京180度, y=北緯210度
在定義型別引數時我們使用了 class,而不是 typename,這樣做的目的是讓讀者對兩種寫法都熟悉。
宣告類模板的語法為:
template<typename 型別引數1 , typename 型別引數2 , …> class 類名{
//TODO:
};
一但聲明瞭類模板,就可以將型別引數用於類的成員函式和成員變量了。換句話說,原來使用 int、float、char 等內建型別的地方,都可以用型別引數來代替。
假如我們現在要定義一個類來表示座標,要求座標的資料型別可以是整數、小數和字串,例如:
- x = 10、y = 10
- x = 12.88、y = 129.65
- x = "東京180度"、y = "北緯210度"
這個時候就可以使用類模板,請看下面的程式碼:
- template<typenameT1, typenameT2> //這裡不能有分號
- classPoint{
- public:
- Point(T1x, T2y): m_x(x), m_y(y){ }
- public:
- T1getX() const; //獲取x座標
- void setX(T1x); //設定x座標
- T2getY() const
- void setY(T2y); //設定y座標
- private:
- T1m_x; //x座標
- T2m_y; //y座標
- };
注意:模板頭和類頭是一個整體,可以換行,但是中間不能有分號。上面的程式碼僅僅是類的宣告,我們還需要在類外定義成員函式。在類外定義成員函式時仍然需要帶上模板頭,格式為:
template<typename 型別引數1 , typename 型別引數2 , …>
返回值型別 類名<型別引數1 , 型別引數2, ...>::函式名(形參列表){
//TODO:
}
下面就對 Point 類的成員函式進行定義:
- template<typenameT1, typenameT2> //模板頭
- T1Point<T1, T2>::getX() const /*函式頭*/ {
- return m_x;
- }
- template<typenameT1, typenameT2>
- void Point<T1, T2>::setX(T1x){
- m_x = x;
- }
- template<typenameT1, typenameT2>
- T2Point<T1, T2>::getY() const{
- return m_y;
- }
- template<typenameT1, typenameT2>
- void Point<T1, T2>::setY(T2y){
- m_y = y;
- }
使用類模板建立物件
上面的兩段程式碼完成了類的定義,接下來就可以使用該類建立物件了。使用類模板建立物件時,需要指明具體的資料型別。請看下面的程式碼:- Point<int, int>p1(10, 20);
- Point<int, float>p2(10, 15.5);
- Point<float, char*>p3(12.4, "東京180度");
除了物件變數,我們也可以使用物件指標的方式來例項化:
- Point<float, float>*p1 = new Point<float, float>(10.6, 109.3);
- Point<char*, char*>*p = new Point<char*, char*>("東京180度", "北緯210度");
- //賦值號兩邊的資料型別不一致
- Point<float, float>*p = new Point<float, int>(10.6, 109);
- //賦值號右邊沒有指明資料型別
- Point<float, float>*p = new Point(10.6, 109);
綜合示例
將上面的類定義和類例項化的程式碼整合起來,構成一個完整的示例,如下所示:- #include <iostream>
- using namespace std;
- template<classT1, classT2> //這裡不能有分號
- classPoint{
- public:
- Point(T1x, T2y): m_x(x), m_y(y){ }
- public:
- T1getX() const; //獲取x座標
- void setX(T1x); //設定x座標
- T2getY() const; //獲取y座標
- void setY(T2y); //設定y座標
- private:
- T1m_x; //x座標
- T2m_y; //y座標
- };
- template<classT1, classT2> //模板頭
- T1Point<T1, T2>::getX() const /*函式頭*/ {
- return m_x;
- }
- template<classT1, classT2>
- void Point<T1, T2>::setX(T1x){
- m_x = x;
- }
- template<classT1, classT2>
- T2Point<T1, T2>::getY() const{
- return m_y;
- }
- template<classT1, classT2>
- void Point<T1, T2>::setY(T2y){
- m_y = y;
- }
- int main(){
- Point<int, int>p1(10, 20);
- cout<<"x="<<p1.getX()<<", y="<<p1.getY()<<endl;
- Point<int, char*>p2(10, "東京180度");
- cout<<"x="<<p2.getX()<<", y="<<p2.getY()<<endl;
- Point<char*, char*>*p3 = new Point<char*, char*>("東京180度", "北緯210度");
- cout<<"x="<<p3->getX()<<", y="<<p3->getY()<<endl;
- return 0;
- }
x=10, y=20
x=10, y=東京180度
x=東京180度, y=北緯210度
在定義型別引數時我們使用了 class,而不是 typename,這樣做的目的是讓讀者對兩種寫法都熟悉。