1. 什麽是C++模板?
答:模板就是實現代碼重用機制的一種工具。它實現了將類型參數化,就是將類型定義為參數,實現了真正的代碼可重用性。模板分為兩大類:函數模板和類模板。由於類模板包含類型參數,所以類模板又稱作參數化的類。如果說類是對象的抽象,抽象是類的實例;那麽可以說類模板是類的抽象,而類是類模板的實例。利用類模板可以建立各種數據類型的類。
2.為什麽要引入模板機制呢?
答:為了實現代碼重用,避免或者減少做重復性的工作,以及避免因重載函數定義不全面引起的調用錯誤等。
3.如何使用(實現)?
(1)函數模板的形式:

Template <class或者也可以用typename T>//函數(類)模板的聲明

返回類型 函數名(形參表)//函數模板的定義/實現
{
  //函數定義體
}
說明:①template 是聲明模板的關鍵字;class可以被typename代替;T是虛擬類型參數,可以被任何字母,字符串或者數字代替。
          ②當模板類和重載函數一起使用時,會首先考慮重載函數,其次是模板類,再沒有的話會考慮類型轉換(可能會不精確)。
測試實例:

//main.cpp
#include <iostream>

using std::cout;
using std::endl;
//聲明一個函數模板,用來比較輸入的兩個相同數據類型參數的大小,class也可以被typename代替
//T可以被任意字母或者數字代替
template <typename T>
T max(T x, T y)
{
    return (x > y) ? x : y;
}

int main()
{
    int n1 = 2, n2 = 10;
    float d1 = 1.5, d2 = 5.6;

    cout << "Integer result is:" << max(n1, n2) << endl;
    cout << "Real result is:" << max(d1, d2) << endl;

    return 0;
}
(2)模板類

template <class 類型參數名>//聲明模板類
class 具體類型參數名 //定義具體類
{
   //...
}
舉例:
比如在未使用模板類之前:要對兩個整數作比較:

class Compare_integer
{
public :
   Compare(int a,int b)
   {
      x=a;
      y=b;
   }
   int max( )
   {
      return (x>y)?x:y;
   }
   int min( )
   {
     return (x<y)?x:y;
   }
private :
   int x,y;
};
如果你又想對double類型的數據作比較呢,就得重新定義一個新的類來實現:

class Compare_double
{
public :
   Compare(double a,double b)
   {
      x=a;
      y=b;
   }
   double max()
   {
      return (x>y)?x:y;
   }
   double min()
   {
      return (x<y)?x:y;
   }
private :
   double x,y;
}
這樣就會比較麻煩。做的重復性的工作很多,使用了模板機制以後就可以減少這些問題。可以聲明一個通用的類模板,它可以有一個或多個虛擬的類型參數,比如對上面兩個類可以綜合寫出以下的類模板:

template <class numtype>
class Compare
{
public :
   Compare(numtype a,numtype b)
   {
     x=a;
     y=b;
   }
   numtype max()
   {
     return (x>y)?x:y;
   }
   numtype min()
   {
     return (x<y)?x:y;
   }
private :
   numtype x,y;
}
將這個類模板和前面的兩個類作比較,會發現:
1>多出了一行template <class numtype> 即聲明類模板時要先加上一行template
2>原有的類型名int換成虛擬類型參數名numtype.這樣在建立類對象時,如果將實際類型指定為int型,編譯系統就會用int取代所有的numtype,如果指定為double型,就用double取代所有的numtype。這樣就能實現“一類多用”。

在聲明了一個類模板之後,如何使用它,將它變成一個實際的類呢?
回想一般的定義一個對象的方法:

Compare_double cmp(2.3, 5.8);//Compare_double是已經聲明的類
用類模板來定義對象的方法和上面的方法類似,但是不能直接那麽寫。Compare是一個類模板名,而不是一個具體類;numtype是一個虛擬類型,而不是一個具體類型;因此無法用它去定義一個對象。而必須用實際的類型名取代虛擬類型,具體做法:

Compare<double> cmp(2.3, 5.8);
即在類模板名之後的尖括號內指定實際的類型名,在進行編譯時,編譯系統就用double取代類模板中的類型參數numtype,這樣就把類模板具體化了,或者說實例化了。這時Compare就相當於前面介紹的Compare_double類。
註意:前面的類模板中的成員函數是在類模板內定義的,如果改為在類模板外定義,則不能使用一般的定義類成員函數的方法:

numtype Compare::max(){...}
而應該寫成類模板的形式:

template <class numtype>
numtype Compare<numtype>::max()
{
   return (x>y)?x:y;
}
總結上面的學習,可以這樣聲明和使用類模板:
1)先寫出一個實際的類。其語義明確,含義清楚。一般不會錯。
2)將該類中準備改變的類型名(比如Int要改為char、double等)改為一個自己指定的虛擬類型名(比如上面例子中的numtype)。
3)在類的聲明前加一行:
     template 。
4)使用類模板定義對象時使用如下形式:

類模板名<實際類型名> 對象名;
類模板名<實際類型名> 對象名(實參列表);
5)如果在類模板之外定義成員函數,應該寫成類模板形式:

template <class 虛擬參數類型>
函數類型 類模板名<虛擬參數類型>::成員函數名(函數形參列表){...}

註意:
1)類模板的類型參數可以有一個或者多個,每個類型前面都必須加class,如:

template <class T1,class T2>
class someclass
{…};
在定義對象名時,分別帶入實際的類型名,比如:

someclass<int, char> Obj;
2)和使用普通類一樣,在使用模板類時一定要註意其作用域。
3)模板也可以有層次,一個類模板可以作為基類,可以派生出派生模板類。
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 愛在屋簷下 的頭像
    愛在屋簷下

    愛在屋簷下的部落格

    愛在屋簷下 發表在 痞客邦 留言(0) 人氣()