C++總結之template

函數模板

咱們能夠把函數模板當作一種特殊的函數,裏面的參數類型能夠是任意類型,這樣的話咱們就能夠減小重複定義,從而讓這個函數模板自動適應不一樣的參數類型,也就是說函數能夠適應多種類型的參數,例如doubleint或者類什麼的。ios

C++爲了實現上面的功能,引入了template這個概念。咱們能夠把template當成是一種特殊的類型參數,而且也能夠在函數裏當作參數傳遞,內心面把它當作int什麼的就好了。ide

使用類型參數聲明函數模板的格式以下所示:函數

template <class identifier> function_declaration;
template <typename identifier> function_declaration;    // 這裏使用了typename 當作聲明類型參數

上面聲明函數模板的格式只有一處不一樣,那就是classtypename,在這裏其實使用哪種都沒有區別,看本身喜歡就行,C++對此也沒有作嚴格的區分;spa

爲了更好的說明如何使用函數模板,便在舉一個很形象的例子,那就是一個用來返回較大值的函數,具體寫法以下所示:code

template <typename T>
T GetMax(T a, T b)
    return a > b ? a : b;

在上面的短短几行代碼中咱們就建立了一個函數模板用來獲取兩個數之間較大的那個數,不難看出T在這裏並無指明具體的類型,在這咱們仍然能夠在內心把它當作普通變量處理,返回值也是T。接口

爲了使用咱們定義的函數模板,能夠參照統一的函數模板調用格式:element

function_name<type> (parameters);    // type就是具體的類型,例如int、double這些,parameters就是函數裏的參數,也是具體類型

因此,若是咱們想要實現獲取兩個整形值裏較大的那個,咱們能夠傳入int這個類型以後調用GetMax函數,具體示例以下:get

int x = 4;
int y = 2;

int max = GetMax<int> (x, y);    // max = 4

類模板

因爲template聲明的類型能夠是任意類型,也就是使用的時候傳入具體的類型就行。因此能夠參考上面函數模板的例子構造類模板也是同樣的,在使用這個類的時候傳入具體的變量類型就好了。例以下面的類模板定義:io

template <typename T>
class MyPair{
    T value[2];
    
    public:
        MyPair(T first, T second)
        {
            value[0] = first;
            value[1] = second;
        }
  };

類模板的示例代碼中定義一個MyPair類,用來存儲任意類型的兩個元素,例如doublecharint等,下面我就給出兩個示例,分別存儲doubleint類型的變量function

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也能夠具備其餘類型的參數,例如intdouble這些參數,就相似於一個函數中擁有多個參數,每一個參數類型還不同。爲了更好的說明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;
}
相關文章
相關標籤/搜索