1. 程式人生 > >C++學習之路(47)---C++類模板與模板類深入詳解

C++學習之路(47)---C++類模板與模板類深入詳解

1、在c++的Template中很多地方都用到了typename與class這兩個關鍵字,而且有時候二者可以替換,那麼是不是這兩個關鍵字完全一樣呢?
事實上class用於定義類,在模板引入c++後,最初定義模板的方法為:template<class T>,這裡class關鍵字表明T是一個型別,後來為了避免class在這兩個地方的使用可能給人帶來混淆,所以引入了typename這個關鍵字,它的作用同class一樣表明後面的符號為一個型別,這樣在定義模板的時候就可以使用下面的方式了:      template<typename T>.在模板定義語法中關鍵字class與typename的作用完全一樣。

2、類模板與模板類的概念

(1) 什麼是類模板

一個類模板(也稱為類屬類或類生成類)允許使用者為類定義一種模式,使得類中的某些資料成員、預設成員函式的引數、某些成員函式的返回值,能夠取任意型別(包括系統預定義的和使用者自定義的)。
如果一個類中資料成員的資料型別不能確定,或者是某個成員函式的引數或返回值的型別不能確定,就必須將此類宣告為模板,它的存在不是代表一個具體的、實際的類,而是代表著一類類。

(2)類模板定義

定義一個類模板,一般有兩方面的內容:

A.首先要定義類,其格式為:

1

2

3

4

5

template

<classT>

classfoo

{

……

}

foo 為類名,在類定義體中,如採用通用資料型別的成員,函式引數的前面需加上T,其中通用型別T可以作為普通成員變數的型別,還可以作為const和static成員變數以及成員函式的引數和返回型別之用。例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

template<classT>

classTest{

private:

T n;

constT i;

staticT cnt;

public:

Test():i(0){}

Test(T k);

~Test(){}

voidprint();

T operator+(T x);

};

B. 在類定義體外定義成員函式時,若此成員函式中有模板引數存在,則除了需要和一般類的體外定義成員函式一樣的定義外,還需在函式體外進行模板宣告

例如:

1

2

3

4

5

6

template<classT>

voidTest<T>::print(){

std::cout<<"n="<<n<<std::endl;

std::cout<<"i="<<i<<std::endl;

std::cout<<"cnt="<<cnt<<std::endl;

}

如果函式是以通用型別為返回型別,則要在函式名前的類名字尾上"<T>".例如:

1

2

3

4

5

6

template<classT>

Test<T>::Test(T k):i(k){n=k;cnt++;}

template<classT>

T Test<T>::operator+(T x){

returnn + x;

}

C. 在類定義體外初始化const成員和static成員變數的做法和普通類體外初始化const成員和static成員變數的做法基本上是一樣的,唯一的區別是需再對模板進行宣告,例如

1

2

3

4

template<classT>

intTest<T>::cnt=0;

template<classT>

Test<T>::Test(T k):i(k){n=k;cnt++;}

(3)類模板的使用。類模板的使用實際上是將類模板例項化成一個具體的類,它的格式為:類名<實際的型別>.
模板類是類模板例項化後的一個產物。說個形象點的例子吧。我們把類模板比作一個做餅乾的模子,而模板類就是用這個模子做出來的餅乾,至於這個餅乾是什麼味道的就要看你自己在例項化時用的是什麼材料了,你可以做巧克力餅乾,也可以做豆沙餅乾,這些餅乾的除了材料不一樣外,其他的東西都是一樣的了。

3、函式模板和模板函式

(1)函式模板
函式模板可以用來建立一個通用的函式,以支援多種不同的形參,避免過載函式的函式體重複設計。它的最大特點是把函式使用的資料型別作為引數。
函式模板的宣告形式為:

1

2

3

4

5

template<typename(或class) T>

<返回型別><函式名>(引數表)

{

函式體

}

其中,template是定義模板函式的關鍵字;template後面的尖括號不能省略;typename(或class)是宣告資料型別引數識別符號的關鍵字,用以說明它後面的識別符號是資料型別識別符號。這樣,在以後定義的這個函式中,凡希望根據實引數據型別來確定資料型別的變數,都可以用資料型別引數識別符號來說明,從而使這個變數可以適應不同的資料型別。例如:

1

2

3

4

5

6

template<typename(或class) T>

T fuc(T x, T y)

{

T x;

//……

}

函式模板只是聲明瞭一個函式的描述即模板,不是一個可以直接執行的函式,只有根據實際情況用實參的資料型別代替型別引數識別符號之後,才能產生真正的函式。

(2)模板函式:
模板函式的生成就是將函式模板的型別形參例項化的過程。
例如:

1

2

3

doubled;

inta;

fuc(d,a);

則系統將用實參d的資料型別double去代替函式模板中的T生成函式:

1

2

3

4

5

doublefuc(doublex,inty)

{

doublex;

//……

}