天天看點

C++函數模闆 模闆執行個體化、具體化

C++函數模闆 模闆執行個體化、具體化

    函數模闆是C++新增的一種性質,它允許隻定義一次函數的實作,即可使用不同類型的參數來調用該函數。這樣做可以減小代碼的書寫的複雜度,同時也便于修改(注:使用模闆函數并不會減少最終可執行程式的大小,因為在調用模闆函數時,編譯器都根據調用時的參數類型進行了相應執行個體化)。下面來看看函數模闆的使用過程:

struct job

{

    char name[20];

    int salary;

};

template <class T> //函數模闆聲明,通用變量類型為T

void swap(T &a, T &b);

void showJob(const job &a);//列印job内容

using std::cin;

using std::cout;

using std::endl;

void main(void)

{

    int a = 4;

    int b = 5;

    cout<<"Before swap a = "<<a<<" b="<<b<<endl;

    swap(a, b);

    cout<<"After swap a = "<<a<<" b="<<b<<endl;

    job jobA = {"coder", 10000};

    job jobB = {"manager", 1000};  

    cout<<"Before swap";

    showJob(jobA);

    showJob(jobB);

    cout<<endl;

    swap(jobA, jobB);

    cout<<"After swap";

    showJob(jobA);

    showJob(jobB);

    cout<<endl;

system("pause");

};

template<class T> //函數模闆實作

void swap(T &a, T &b)

{

    T temp;

    temp = a;

    a = b;

    b = temp;

}

void showJob(const job &a)

{

cout<<" "<<a.name<<" = "<<a.salary;

}

如果在上述job結構互換過程中隻想互換salary,而不換其他成員變量值那麼怎麼辦呢?C++中可以通過以下幾種方法來解決這一問題。

1>顯式具體化

顯式具體化也是基于函數模闆的,隻不過在函數模闆的基礎上,添加一個專門針對特定類型的、實作方式不同的具體化函數。

template<>void swap<job>(job &a, job &b)

{

     int salary;

     salary = a.salary;

     a.salary = b.salary;

     b.salary = salary;

}

如上所示,該具體化函數的實作與模闆并不一緻,編譯器解析函數調用時會選擇最比對的函數定義。

2>定義同名正常函數

void swap(job &a, job &b)

{

     int salary;

     salary = a.salary;

     a.salary = b.salary;

     b.salary = salary;

}

由于編譯器在重載解析時,會選擇最比對函數定義,是以在調用swap(jobA, jobB)時,編譯器會選擇void swap(job &a, job &b)函數定義,而屏蔽了模闆函數。

同時,模闆函數也可以重載,其操作與正常函數一緻。

template <class T> void swap(T &a, T &b);

template <class T> void swap(T &a, T &b, T &c);

template <typename T> void swap(T &a, T &b)

{

    T temp;

    temp = a;

    a = b;

    b = temp;

}

template <typename T> void swap(T &a, T &b, T &c)

{

    T temp;

    temp = a;

    a = b;

    b = c;

    c = temp;

}

上面主要說的是函數模闆的具體化,下面說下模闆執行個體化。

函數模闆:

#define MAXNAME 128

struct job

{

char name[MAXNAME]:

int salary;

};

template<class T>

void swap(T &a, T &b )

{

  T temp;

  temp = a;

  a = b;

  b = temp;

};

template void swap<int>(int &a, int & b);  //顯式執行個體化,隻需聲明

template<> void swap<job>(job &a, job &b)   //顯式具體化(上面已經講過,注意與執行個體化區分開,必須有定義)

{

  int salary:

  salary = a.salary:

  a.salary = b.salary;

  b.salary = salary;

};//explicite specialization.

類模闆:

template <class T>

class Arrary

{

private:

  T* ar;

  int l;

...

};//template class declaration.

template class Array<int>;   //explicit instantiation. 顯式執行個體化

template<> class Array<job>

{

private:

  job* ar;

  int l;

};//expicit specialization.   顯式具體化,類定義體可以不同于類模闆Array

相應的,隐式執行個體化指的是:在使用模闆之前,編譯器不生成模闆的聲明和定義執行個體。隻有當使用模闆時,編譯器才根據模闆定義生成相應類型的執行個體。如:

int i=0, j=1;

swap(i, j);  //編譯器根據參數i,j的類型隐式地生成swap<int>(int &a, int &b)的函數定義。

Array<int> arVal;//編譯器根據類型參數隐式地生成Array<int>類聲明和類函數定義。

顯式執行個體化:

當顯式執行個體化模闆時,在使用模闆之前,編譯器根據顯式執行個體化指定的類型生成模闆執行個體。如前面顯示執行個體化(explicit instantiation)模闆函數和模闆類。其格式為:

template typename function<typename>(argulist);

template class classname<typename>;

顯式執行個體化隻需聲明,不需要重新定義。編譯器根據模闆實作執行個體聲明和執行個體定義。

顯示具體化:

對于某些特殊類型,可能不适合模闆實作,需要重新定義實作,此時可以使用顯示具體化(explicite specialization)。顯示執行個體化需重新定義。格式為:

template<> typename function<typename>(argu_list){...};

template<> class classname<typename>{...};

綜上:

template<> void swap<job>(job &a, job &b) {……};是函數模闆的顯式具體化,意思是job類型不适用于函數模闆swap的定義,是以通過這個顯式具體化重新定義;也可簡寫作template<> void swap(job &a, job &b);

template void swap<job>(job &a, job &b);是函數模闆的一個顯式執行個體化,隻需聲明,編譯器遇到這種顯式執行個體化,會根據原模闆的定義及該聲明直接生成一個執行個體函數,該函數僅接受job型。否則編譯器遇到模闆的使用時才會隐式的生成相應的執行個體函數。

繼續閱讀