日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 高级篇(一)—— 模板(Templates)

發(fā)布時間:2023/12/9 c/c++ 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 高级篇(一)—— 模板(Templates) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


模板(Templates)是ANSI-C++ 標(biāo)準(zhǔn)中新引入的概念。如果你使用的 C++ 編譯器不符合這個標(biāo)準(zhǔn),則你很可能不能使用模板。

?

?

函數(shù)模板( Function templates)

模板(Templates)使得我們可以生成通用的函數(shù),這些函數(shù)能夠接受任意數(shù)據(jù)類型的參數(shù),可返回任意類型的值,而不需要對所有可能的數(shù)據(jù)類型進(jìn)行函數(shù)重載。這在一定程度上實現(xiàn)了宏(macro)的作用。它們的原型定義可以是下面兩種中的任何一個:

template <class identifier>?function_declaration;
template <typename identifier>?function_declaration;

上面兩種原型定義的不同之處在關(guān)鍵字class 或 typename的使用。它們實際是完全等價的,因為兩種表達(dá)的意思和執(zhí)行都一模一樣。

例如,要生成一個模板,返回兩個對象中較大的一個,我們可以這樣寫:

template <class GenericType>

GenericType GetMax (GenericType a, GenericType b) { return (a>b?a:b); }

在第一行聲明中,我們已經(jīng)生成了一個通用數(shù)據(jù)類型的模板,叫做GenericType。因此在其后面的函數(shù)中,GenericType 成為一個有效的數(shù)據(jù)類型,它被用來定義了兩個參數(shù)a和 b ,并被用作了函數(shù)GetMax的返回值類型。

GenericType 仍沒有代表任何具體的數(shù)據(jù)類型;當(dāng)函數(shù) GetMax 被調(diào)用的時候,我們可以使用任何有效的數(shù)據(jù)類型來調(diào)用它。這個數(shù)據(jù)類型將被作為pattern來代替函數(shù)中GenericType 出現(xiàn)的地方。用一個類型pattern來調(diào)用一個模板的方法如下:

function <type>?(parameters);

例如,要調(diào)用GetMax 來比較兩個int類型的整數(shù)可以這樣寫:

int x,y;
GetMax <int>?(x,y);

因此,GetMax 的調(diào)用就好像所有的GenericType 出現(xiàn)的地方都用int 來代替一樣。

這里是一個例子:

// function template

#include <iostream.h>

template <class T> T GetMax (T a, T b) {

??? T result;

??? result = (a>b)? a : b;

??? return (result);

}

int main () {

??? int i=5, j=6, k;

??? long l=10, m=5, n;

??? k=GetMax(i,j);

??? n=GetMax(l,m);

??? cout << k << endl;

??? cout << n << endl;

??? return 0;
}

6
10

(在這個例子中,我們將通用數(shù)據(jù)類型命名為T 而不是 GenericType ,因為T短一些,并且它是模板更為通用的標(biāo)示之一,雖然使用任何有效的標(biāo)示符都是可以的。)

在上面的例子中,我們對同樣的函數(shù)GetMax()使用了兩種參數(shù)類型:int 和 long,而只寫了一種函數(shù)的實現(xiàn),也就是說我們寫了一個函數(shù)的模板,用了兩種不同的pattern來調(diào)用它。

如你所見,在我們的模板函數(shù) GetMax() 里,類型 T 可以被用來聲明新的對象

T result;

result 是一個T類型的對象, 就像a 和 b一樣,也就是說,它們都是同一類型的,這種類型就是當(dāng)我們調(diào)用模板函數(shù)時寫在尖括號<> 中的類型。

在這個具體的例子中,通用類型 T 被用作函數(shù)GetMax 的參數(shù),不需要說明<int>或 <long>,編譯器也可以自動檢測到傳入的數(shù)據(jù)類型,因此,我們也可以這樣寫這個例子:

int i,j;
GetMax (i,j);

因為i 和j 都是int 類型,編譯器會自動假設(shè)我們想要函數(shù)按照int進(jìn)行調(diào)用。這種暗示的方法更為有用,并產(chǎn)生同樣的結(jié)果:

// function template II

#include <iostream.h>

template <class T> T GetMax (T a, T b) {

??? return (a>b?a:b);

}

int main () {

??? int i=5, j=6, k;

??? long l=10, m=5, n;

??? k=GetMax(i,j);

??? n=GetMax(l,m);

??? cout << k << endl;

??? cout << n << endl;

??? return 0;

}

6
10

注意在這個例子的main() 中我們?nèi)绾握{(diào)用模板函數(shù)GetMax() 而沒有在括號<>中指明具體數(shù)據(jù)類型的。編譯器自動決定每一個調(diào)用需要什么數(shù)據(jù)類型。

因為我們的模板函數(shù)只包括一種數(shù)據(jù)類型 (class T), 而且它的兩個參數(shù)都是同一種類型,我們不能夠用兩個不同類型的參數(shù)來調(diào)用它:

int i;
long l;
k = GetMax (i,l);

上面的調(diào)用就是不對的,因為我們的函數(shù)等待的是兩個同種類型的參數(shù)。

我們也可以使得模板函數(shù)接受兩種或兩種以上類型的數(shù)據(jù),例如:

template <class T>

T GetMin (T a, U b) { return (a<b?a:b); }

在這個例子中,我們的模板函數(shù) GetMin() 接受兩個不同類型的參數(shù),并返回一個與第一個參數(shù)同類型的對象。在這種定義下,我們可以這樣調(diào)用該函數(shù):

int i,j;
long l;
i = GetMin <int, long>?(j,l);

或者,簡單的用

i = GetMin (j,l);

雖然 j 和 l 是不同的類型。

?

類模板(Class templates)

我們也可以定義類模板(class templates),使得一個類可以有基于通用類型的成員,而不需要在類生成的時候定義具體的數(shù)據(jù)類型,例如:

template <class T>

class pair {

??? T values [2];

public:

??? pair (T first, T second) {

??????? values[0]=first;

??????? values[1]=second;

??? }

};

上面我們定義的類可以用來存儲兩個任意類型的元素。例如,如果我們想要定義該類的一個對象,用來存儲兩個整型數(shù)據(jù)115 和 36 ,我們可以這樣寫:

pair<int> myobject (115, 36);

我們同時可以用這個類來生成另一個對象用來存儲任何其他類型數(shù)據(jù),例如:

pair<float> myfloats (3.0, 2.18);

在上面的例子中,類的唯一一個成員函數(shù)已經(jīng)被inline 定義。如果我們要在類之外定義它的一個成員函數(shù),我們必須在每一函數(shù)前面加template <... >。

// class templates

#include <iostream.h>

template <class T> class pair {
???? T value1, value2;
public:
??? pair (T first, T second) {

??????? value1=first;

??????? value2=second;

??? }

??? T getmax ();

};

template <class T>

T pair::getmax (){

??? T retval;

??? retval = value1>value2? value1 : value2;

??? return retval;

}

int main () {

??? pair?myobject (100, 75);

??? cout << myobject.getmax();

??? return 0;

}

100

注意成員函數(shù)getmax 是怎樣開始定義的:

template <class T>
T pair::getmax ()

所有寫 T 的地方都是必需的,每次你定義模板類的成員函數(shù)的時候都需要遵循類似的格式(這里第二個T表示函數(shù)返回值的類型,這個根據(jù)需要可能會有變化)。

?

模板特殊化(Template specialization)

模板的特殊化是當(dāng)模板中的pattern有確定的類型時,模板有一個具體的實現(xiàn)。例如假設(shè)我們的類模板pair 包含一個取模計算(module operation)的函數(shù),而我們希望這個函數(shù)只有當(dāng)對象中存儲的數(shù)據(jù)為整型(int)的時候才能工作,其他時候,我們需要這個函數(shù)總是返回0。這可以通過下面的代碼來實現(xiàn):

// Template specialization

#include <iostream.h>

template <class T> class pair {

??? T value1, value2;

public:

??? pair (T first, T second){

??????? value1=first;

??????? value2=second;

??? }

??? T module () {return 0;}

};

template <>

class pair <int>?{

??? int value1, value2;

public:

??? pair (int first, int second){

??????? value1=first;

??????? value2=second;

??? }

??? int module ();

};

template <>

int pair<int>::module() {

??? return value1%value2;

}

int main () {

??? pair <int> myints (100,75);

??? pair <float> myfloats (100.0,75.0);

??? cout << myints.module() << '\n';

??? cout << myfloats.module() << '\n';

??? return 0;

}

25
0

由上面的代碼可以看到,模板特殊化由以下格式定義:

template <> class class_name <type>

這個特殊化本身也是模板定義的一部分,因此,我們必須在該定義開頭寫template <>。而且因為它確實為一個具體類型的特殊定義,通用數(shù)據(jù)類型在這里不能夠使用,所以第一對尖括號<> 內(nèi)必須為空。在類名稱后面,我們必須將這個特殊化中使用的具體數(shù)據(jù)類型寫在尖括號<>中。

當(dāng)我們特殊化模板的一個數(shù)據(jù)類型的時候,同時還必須重新定義類的所有成員的特殊化實現(xiàn)(如果你仔細(xì)看上面的例子,會發(fā)現(xiàn)我們不得不在特殊化的定義中包含它自己的構(gòu)造函數(shù) constructor,雖然它與通用模板中的構(gòu)造函數(shù)是一樣的)。這樣做的原因就是特殊化不會繼承通用模板的任何一個成員。

?

模板的參數(shù)值(Parameter values for templates)

除了模板參數(shù)前面跟關(guān)鍵字class 或 typename 表示一個通用類型外,函數(shù)模板和類模板還可以包含其它不是代表一個類型的參數(shù),例如代表一個常數(shù),這些通常是基本數(shù)據(jù)類型的。例如,下面的例子定義了一個用來存儲數(shù)組的類模板:

// array template

#include <iostream.h>

template <class T,?int N>

class array {

??? T memblock [N];

public:

??? void setmember (int x, T value);

??? T getmember (int x);

};

template <class T, int N>

void array<T,N>::setmember (int x, T value) {

??? memblock[x]=value;

}

template <class T, int N>

T array<T,N>::getmember (int x) {

??? return memblock[x];

}

int main () {

??? array <int,5> myints;

??? array <float,5> myfloats;

??? myints.setmember (0,100);

??? myfloats.setmember (3,3.1416);

??? cout << myints.getmember(0) << '\n';

??? cout << myfloats.getmember(3) << '\n';

??? return 0;

}

100
3.1416

我們也可以為模板參數(shù)設(shè)置默認(rèn)值,就像為函數(shù)參數(shù)設(shè)置默認(rèn)值一樣。

下面是一些模板定義的例子:

template <class T>?// 最常用的:一個class 參數(shù)。

template <class T, class U>?// 兩個class 參數(shù)。

template <class T, int N>?// 一個class 和一個整數(shù)。

template <class T = char>?// 有一個默認(rèn)值。

template <int Tfunc (int)>?// 參數(shù)為一個函數(shù)。

?

模板與多文件工程 (Templates and multiple-file projects)

從編譯器的角度來看,模板不同于一般的函數(shù)或類。它們在需要時才被編譯(compiled on demand),也就是說一個模板的代碼直到需要生成一個對象的時候(instantiation)才被編譯。當(dāng)需要instantiation的時候,編譯器根據(jù)模板為特定的調(diào)用數(shù)據(jù)類型生成一個特殊的函數(shù)。

當(dāng)工程變得越來越大的時候,程序代碼通常會被分割為多個源程序文件。在這種情況下,通常接口(interface)和實現(xiàn)(implementation)是分開的。用一個函數(shù)庫做例子,接口通常包括所有能被調(diào)用的函數(shù)的原型定義。它們通常被定義在以.h 為擴展名的頭文件 (header file) 中;而實現(xiàn) (函數(shù)的定義) 則在獨立的C++代碼文件中。

模板這種類似宏(macro-like) 的功能,對多文件工程有一定的限制:函數(shù)或類模板的實現(xiàn) (定義) 必須與原型聲明在同一個文件中。也就是說我們不能再 將接口(interface)存儲在單獨的頭文件中,而必須將接口和實現(xiàn)放在使用模板的同一個文件中。

回到函數(shù)庫的例子,如果我們想要建立一個函數(shù)模板的庫,我們不能再使用頭文件(.h) ,取而代之,我們應(yīng)該生成一個模板文件(template file),將函數(shù)模板的接口和實現(xiàn) 都放在這個文件中 (這種文件沒有慣用擴展名,除了不要使用.h擴展名或不要不加任何擴展名)。在一個工程中多次包含同時具有聲明和實現(xiàn)的模板文件并不會產(chǎn)生鏈接錯誤 (linkage errors),因為它們只有在需要時才被編譯,而兼容模板的編譯器應(yīng)該已經(jīng)考慮到這種情況,不會生成重復(fù)的代碼。

模板(Templates)是ANSI-C++ 標(biāo)準(zhǔn)中新引入的概念。如果你使用的 C++ 編譯器不符合這個標(biāo)準(zhǔn),則你很可能不能使用模板。

?

?

函數(shù)模板( Function templates)

模板(Templates)使得我們可以生成通用的函數(shù),這些函數(shù)能夠接受任意數(shù)據(jù)類型的參數(shù),可返回任意類型的值,而不需要對所有可能的數(shù)據(jù)類型進(jìn)行函數(shù)重載。這在一定程度上實現(xiàn)了宏(macro)的作用。它們的原型定義可以是下面兩種中的任何一個:

template <class identifier>?function_declaration;
template <typename identifier>?function_declaration;

上面兩種原型定義的不同之處在關(guān)鍵字class 或 typename的使用。它們實際是完全等價的,因為兩種表達(dá)的意思和執(zhí)行都一模一樣。

例如,要生成一個模板,返回兩個對象中較大的一個,我們可以這樣寫:

template <class GenericType>

GenericType GetMax (GenericType a, GenericType b) { return (a>b?a:b); }

在第一行聲明中,我們已經(jīng)生成了一個通用數(shù)據(jù)類型的模板,叫做GenericType。因此在其后面的函數(shù)中,GenericType 成為一個有效的數(shù)據(jù)類型,它被用來定義了兩個參數(shù)a和 b ,并被用作了函數(shù)GetMax的返回值類型。

GenericType 仍沒有代表任何具體的數(shù)據(jù)類型;當(dāng)函數(shù) GetMax 被調(diào)用的時候,我們可以使用任何有效的數(shù)據(jù)類型來調(diào)用它。這個數(shù)據(jù)類型將被作為pattern來代替函數(shù)中GenericType 出現(xiàn)的地方。用一個類型pattern來調(diào)用一個模板的方法如下:

function <type>?(parameters);

例如,要調(diào)用GetMax 來比較兩個int類型的整數(shù)可以這樣寫:

int x,y;
GetMax <int>?(x,y);

因此,GetMax 的調(diào)用就好像所有的GenericType 出現(xiàn)的地方都用int 來代替一樣。

這里是一個例子:

// function template

#include <iostream.h>

template <class T> T GetMax (T a, T b) {

??? T result;

??? result = (a>b)? a : b;

??? return (result);

}

int main () {

??? int i=5, j=6, k;

??? long l=10, m=5, n;

??? k=GetMax(i,j);

??? n=GetMax(l,m);

??? cout << k << endl;

??? cout << n << endl;

??? return 0;
}

6
10

(在這個例子中,我們將通用數(shù)據(jù)類型命名為T 而不是 GenericType ,因為T短一些,并且它是模板更為通用的標(biāo)示之一,雖然使用任何有效的標(biāo)示符都是可以的。)

在上面的例子中,我們對同樣的函數(shù)GetMax()使用了兩種參數(shù)類型:int 和 long,而只寫了一種函數(shù)的實現(xiàn),也就是說我們寫了一個函數(shù)的模板,用了兩種不同的pattern來調(diào)用它。

如你所見,在我們的模板函數(shù) GetMax() 里,類型 T 可以被用來聲明新的對象

T result;

result 是一個T類型的對象, 就像a 和 b一樣,也就是說,它們都是同一類型的,這種類型就是當(dāng)我們調(diào)用模板函數(shù)時寫在尖括號<> 中的類型。

在這個具體的例子中,通用類型 T 被用作函數(shù)GetMax 的參數(shù),不需要說明<int>或 <long>,編譯器也可以自動檢測到傳入的數(shù)據(jù)類型,因此,我們也可以這樣寫這個例子:

int i,j;
GetMax (i,j);

因為i 和j 都是int 類型,編譯器會自動假設(shè)我們想要函數(shù)按照int進(jìn)行調(diào)用。這種暗示的方法更為有用,并產(chǎn)生同樣的結(jié)果:

// function template II

#include <iostream.h>

template <class T> T GetMax (T a, T b) {

??? return (a>b?a:b);

}

int main () {

??? int i=5, j=6, k;

??? long l=10, m=5, n;

??? k=GetMax(i,j);

??? n=GetMax(l,m);

??? cout << k << endl;

??? cout << n << endl;

??? return 0;

}

6
10

注意在這個例子的main() 中我們?nèi)绾握{(diào)用模板函數(shù)GetMax() 而沒有在括號<>中指明具體數(shù)據(jù)類型的。編譯器自動決定每一個調(diào)用需要什么數(shù)據(jù)類型。

因為我們的模板函數(shù)只包括一種數(shù)據(jù)類型 (class T), 而且它的兩個參數(shù)都是同一種類型,我們不能夠用兩個不同類型的參數(shù)來調(diào)用它:

int i;
long l;
k = GetMax (i,l);

上面的調(diào)用就是不對的,因為我們的函數(shù)等待的是兩個同種類型的參數(shù)。

我們也可以使得模板函數(shù)接受兩種或兩種以上類型的數(shù)據(jù),例如:

template <class T>

T GetMin (T a, U b) { return (a<b?a:b); }

在這個例子中,我們的模板函數(shù) GetMin() 接受兩個不同類型的參數(shù),并返回一個與第一個參數(shù)同類型的對象。在這種定義下,我們可以這樣調(diào)用該函數(shù):

int i,j;
long l;
i = GetMin <int, long>?(j,l);

或者,簡單的用

i = GetMin (j,l);

雖然 j 和 l 是不同的類型。

?

類模板(Class templates)

我們也可以定義類模板(class templates),使得一個類可以有基于通用類型的成員,而不需要在類生成的時候定義具體的數(shù)據(jù)類型,例如:

template <class T>

class pair {

??? T values [2];

public:

??? pair (T first, T second) {

??????? values[0]=first;

??????? values[1]=second;

??? }

};

上面我們定義的類可以用來存儲兩個任意類型的元素。例如,如果我們想要定義該類的一個對象,用來存儲兩個整型數(shù)據(jù)115 和 36 ,我們可以這樣寫:

pair<int> myobject (115, 36);

我們同時可以用這個類來生成另一個對象用來存儲任何其他類型數(shù)據(jù),例如:

pair<float> myfloats (3.0, 2.18);

在上面的例子中,類的唯一一個成員函數(shù)已經(jīng)被inline 定義。如果我們要在類之外定義它的一個成員函數(shù),我們必須在每一函數(shù)前面加template <... >。

// class templates

#include <iostream.h>

template <class T> class pair {
???? T value1, value2;
public:
??? pair (T first, T second) {

??????? value1=first;

??????? value2=second;

??? }

??? T getmax ();

};

template <class T>

T pair::getmax (){

??? T retval;

??? retval = value1>value2? value1 : value2;

??? return retval;

}

int main () {

??? pair?myobject (100, 75);

??? cout << myobject.getmax();

??? return 0;

}

100

注意成員函數(shù)getmax 是怎樣開始定義的:

template <class T>
T pair::getmax ()

所有寫 T 的地方都是必需的,每次你定義模板類的成員函數(shù)的時候都需要遵循類似的格式(這里第二個T表示函數(shù)返回值的類型,這個根據(jù)需要可能會有變化)。

?

模板特殊化(Template specialization)

模板的特殊化是當(dāng)模板中的pattern有確定的類型時,模板有一個具體的實現(xiàn)。例如假設(shè)我們的類模板pair 包含一個取模計算(module operation)的函數(shù),而我們希望這個函數(shù)只有當(dāng)對象中存儲的數(shù)據(jù)為整型(int)的時候才能工作,其他時候,我們需要這個函數(shù)總是返回0。這可以通過下面的代碼來實現(xiàn):

// Template specialization

#include <iostream.h>

template <class T> class pair {

??? T value1, value2;

public:

??? pair (T first, T second){

??????? value1=first;

??????? value2=second;

??? }

??? T module () {return 0;}

};

template <>

class pair <int>?{

??? int value1, value2;

public:

??? pair (int first, int second){

??????? value1=first;

??????? value2=second;

??? }

??? int module ();

};

template <>

int pair<int>::module() {

??? return value1%value2;

}

int main () {

??? pair <int> myints (100,75);

??? pair <float> myfloats (100.0,75.0);

??? cout << myints.module() << '\n';

??? cout << myfloats.module() << '\n';

??? return 0;

}

25
0

由上面的代碼可以看到,模板特殊化由以下格式定義:

template <> class class_name <type>

這個特殊化本身也是模板定義的一部分,因此,我們必須在該定義開頭寫template <>。而且因為它確實為一個具體類型的特殊定義,通用數(shù)據(jù)類型在這里不能夠使用,所以第一對尖括號<> 內(nèi)必須為空。在類名稱后面,我們必須將這個特殊化中使用的具體數(shù)據(jù)類型寫在尖括號<>中。

當(dāng)我們特殊化模板的一個數(shù)據(jù)類型的時候,同時還必須重新定義類的所有成員的特殊化實現(xiàn)(如果你仔細(xì)看上面的例子,會發(fā)現(xiàn)我們不得不在特殊化的定義中包含它自己的構(gòu)造函數(shù) constructor,雖然它與通用模板中的構(gòu)造函數(shù)是一樣的)。這樣做的原因就是特殊化不會繼承通用模板的任何一個成員。

?

模板的參數(shù)值(Parameter values for templates)

除了模板參數(shù)前面跟關(guān)鍵字class 或 typename 表示一個通用類型外,函數(shù)模板和類模板還可以包含其它不是代表一個類型的參數(shù),例如代表一個常數(shù),這些通常是基本數(shù)據(jù)類型的。例如,下面的例子定義了一個用來存儲數(shù)組的類模板:

// array template

#include <iostream.h>

template <class T,?int N>

class array {

??? T memblock [N];

public:

??? void setmember (int x, T value);

??? T getmember (int x);

};

template <class T, int N>

void array<T,N>::setmember (int x, T value) {

??? memblock[x]=value;

}

template <class T, int N>

T array<T,N>::getmember (int x) {

??? return memblock[x];

}

int main () {

??? array <int,5> myints;

??? array <float,5> myfloats;

??? myints.setmember (0,100);

??? myfloats.setmember (3,3.1416);

??? cout << myints.getmember(0) << '\n';

??? cout << myfloats.getmember(3) << '\n';

??? return 0;

}

100
3.1416

我們也可以為模板參數(shù)設(shè)置默認(rèn)值,就像為函數(shù)參數(shù)設(shè)置默認(rèn)值一樣。

下面是一些模板定義的例子:

template <class T>?// 最常用的:一個class 參數(shù)。

template <class T, class U>?// 兩個class 參數(shù)。

template <class T, int N>?// 一個class 和一個整數(shù)。

template <class T = char>?// 有一個默認(rèn)值。

template <int Tfunc (int)>?// 參數(shù)為一個函數(shù)。

?

模板與多文件工程 (Templates and multiple-file projects)

從編譯器的角度來看,模板不同于一般的函數(shù)或類。它們在需要時才被編譯(compiled on demand),也就是說一個模板的代碼直到需要生成一個對象的時候(instantiation)才被編譯。當(dāng)需要instantiation的時候,編譯器根據(jù)模板為特定的調(diào)用數(shù)據(jù)類型生成一個特殊的函數(shù)。

當(dāng)工程變得越來越大的時候,程序代碼通常會被分割為多個源程序文件。在這種情況下,通常接口(interface)和實現(xiàn)(implementation)是分開的。用一個函數(shù)庫做例子,接口通常包括所有能被調(diào)用的函數(shù)的原型定義。它們通常被定義在以.h 為擴展名的頭文件 (header file) 中;而實現(xiàn) (函數(shù)的定義) 則在獨立的C++代碼文件中。

模板這種類似宏(macro-like) 的功能,對多文件工程有一定的限制:函數(shù)或類模板的實現(xiàn) (定義) 必須與原型聲明在同一個文件中。也就是說我們不能再 將接口(interface)存儲在單獨的頭文件中,而必須將接口和實現(xiàn)放在使用模板的同一個文件中。

回到函數(shù)庫的例子,如果我們想要建立一個函數(shù)模板的庫,我們不能再使用頭文件(.h) ,取而代之,我們應(yīng)該生成一個模板文件(template file),將函數(shù)模板的接口和實現(xiàn) 都放在這個文件中 (這種文件沒有慣用擴展名,除了不要使用.h擴展名或不要不加任何擴展名)。在一個工程中多次包含同時具有聲明和實現(xiàn)的模板文件并不會產(chǎn)生鏈接錯誤 (linkage errors),因為它們只有在需要時才被編譯,而兼容模板的編譯器應(yīng)該已經(jīng)考慮到這種情況,不會生成重復(fù)的代碼。

總結(jié)

以上是生活随笔為你收集整理的C++ 高级篇(一)—— 模板(Templates)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。