C 學習之模板

2021-06-19 11:21:38 字數 3782 閱讀 1637

之前寫過有關c++模板的內容,但是現在回頭再看看書本,發現之前寫的東西太膚淺了。考慮的問題太不全面了。因此在這裡重寫下有關c++模板的知識總結。

為什麼c++要引入模板這個概念呢?c++的發明者bjarne stroustrup曾這樣說過:「這是為了支援型別安全、類容器的有效性和演算法的通用性。」簡單的來說,模板就是實現**重用機制的一種工具,它可以實現型別引數化,即把型別定義為引數,從而實現真正的**可重用性。c++中的模板可分為兩類:函式模板和類模板。它們有共同的特點,也存在一定的用法差異。下面我們就分別介紹兩種模板的使用方法和應注意的問題。

一、函式模板

有時我們為了實現不同型別引數的函式要分別寫出各種型別的過載函式,這樣做往往需要寫幾個甚至十幾個只有略微差別的函式。在引入模板的概念之後,我們可以用乙個函式輕鬆的解決這之類的問題了。首先舉乙個簡單的加法運算的例子:

template

t add( t a, t b)

return  a+b;

這個例子就是乙個函式模板,我們可以分別用顯式和隱式的方法呼叫該模板:

1.      顯式的呼叫該模板: add(5,6); add(2.5, 3.4);

2.      隱式的呼叫模板:add(5,6); add(2.5,3.4);雖然這裡沒有顯式的指定函式模板引數,但是它能自動地推導出函式模板引數為int。需要注意的是:模板的型別引數可以不止乙個,比如

template

是可以的。並且當模板的型別引數用於函式的返回型別時,隱式呼叫的自動推導就不會起作用了。比如:

template

t2 add(t1 a, t1 b)

此時呼叫必須是:

add(5,6);

或者add(5.6)

;因為函式返回型別的型別引數是不能自動推導的。

下面就介紹函式模板的幾個特殊用法:

1.      非型別模板引數

這個名字聽起來有點怪怪的,我們來舉個例子來看,就很明了了:

template

t addvalue(t const &x)

return x+val;

當我們執行語句,int i = addvalue(1);結果為6。這樣來看非型別模板引數的概念就有些明朗了,即它表示該引數名代表了乙個潛在的值,而該值代表了模板定義中的乙個常量。而且它是有限制的:它們可以是整形(包括列舉型別)或者指向外部鏈結物件的指標(指向外部鏈結物件的指標?怎麼使用?求高人指點),但它們絕不可能是浮點數和類物件。

接著就介紹一種利用非型別模板引數求陣列大小的方法,也是先舉出例子再作分析:

templateint arrarysize(type (&arr)[size])//注意這裡的格式,這是宣告陣列模板的方法。

int main()

; i = arrarysize(arr);//傳入的只能是陣列名,而不能是乙個指標。

cout<

上面的結果輸出是:9。正確的輸出了陣列的大小,這樣計算總有點怪怪的感覺對吧。其實這是通過自動推導模板引數計算出的size。在具體的怎麼推導,我也不太明白,求高人指點。

2.      預設模板引數

函式模板使用預設模板引數和普通函式使用預設引數的作用一樣,它們的使用方法也類似。比如:

template t square(t a = 1)

square(); // 預設輸出結果1

square(2.0)// 輸出結果4.0

需要注意的是:和普通函式的預設引數一樣,如果函式存在多個引數時,具有預設值的引數必須要放在最右邊,因為實參和形參的結合是從左到右的順序進行的。寫到這裡,讓我想到了:具有預設引數的函式是不能和過載函式共同作用的。因為這樣做了會引起二義性。

3.      函式模板和過載

當同一作用域中既存在函式模板和普通函式時,如果兩者都精確匹配執行語句時,那麼普通函式的呼叫優先順序高於函式模板的優先順序。並且函式模板不支援引數型別的自動轉換。

二、類模板

類模板比函式模板複雜了很多。類包含了繼承,巢狀等複雜的組合關係。首先類模板的宣告是和函式模板一樣的,同樣是增加一行:template template

函式型別  類模板名< typename>::類成員函式名(函式形參表)

靜態成員變數的定義方法:

template變數型別類模板名< typename >::變數名 = 變數值;

類模板也具有非型別的類模板引數,它的用法和函式模板的非型別的模板引數是一樣的。只不過呼叫非型別模板形參的實參必須是乙個常量表示式,或者是乙個數,即它必須能在編譯時計算出結果。類模板也具有預設模板引數,就像為函式引數設定預設值一樣。這些都是和函式模板很相似的,就不許要多說了。下面著重介紹類模板的類外幾個重要的應用。

1.      模板的模板引數

又是乙個怪怪的概念。先從定義上了解它:將乙個模板作為另乙個模板的引數,也即是說型別形參可以是類模板。模板是依靠型別引數來實現的,這個型別引數可以是基本資料型別(int 、long、 double),也可以是自定的資料型別或者stl庫中的資料型別。如果是自定的資料型別,那麼它也可以是乙個模板類,也就是說模板要支援其型別引數是乙個模板類的可能。也就是我們這裡所說的模板的模板引數。

它的乙個簡單的定義是:

templateclass a>

class b

}// 有時候t3可以省略不寫

下面我們舉乙個非常有趣的例子,即:類模板遞迴求平方和

template class f>

class accumulate

; };

template class f>

class accumulate<0,f>

; };

templateclass square

; };

int main()

; virtual void entry()

~localdoor() {}

virtual void entry()

private:

t * m_pobj;

};return new localdoor(data);

}};int main()

上面的輸出結果是:

3.      類模板的派生

類模板的派生和一般類的派生有很大的相似的地方。只不過類模板的派生可包括:從類模板本身繼承;也可以從類模板特定例項化繼承。派生類可以是類模板也可以不是類模板。乙個類模板可以派生成乙個新類模板,派生類模板可以新增新的成員變數和成員函式,以實現類模板的擴充和修改。

3.      模板的特化

模板的特化是乙個重要的概念。它的用途比較廣泛。所謂特化就是將泛型搞得具體化一些,也即是為已有的模板引數進行一些使其特殊化的指定,使得以前不受任何約束的模板引數,或受到特定的修飾或完全被指定了。比如上面提到的add函式的模板,它就不適合求複數的相加,此時我們可以為複數型別特化出來乙個add函式。具體的使用方法是:

template <>

模板名《特化定義的模板引數》(函式形參表)

函式體;

比如對complex型別特化乙個add函式

template<>

complex add(complex cm_a, complex cm_b)

上面就實現了乙個特化。而且需要注意的是:匹配函式的優先順序,非模板函式

>

特化的模板函式

>

模板函式。

類也有特化的類模板,其主要是用於不同的資料型別的實現方法不同,因此要對其做一些特殊處理。這裡就不在舉例說明了。

C 之模板 模板的學習 學習模板

c 之模板 模板學習 學習模板 模板就是建立通用的模具,大大提高復用性 函式模板 c 提供兩種模板機制函式模板和類模板 函式模板語法 函式模板作用 建立乙個通用函式,其函式返回值型別和形參型別可以不具體制定,用乙個虛擬的型別來代表 語法 template typename t 函式宣告或定義解釋 t...

C 學習之模板

有關c 模板的概念,詳細學過c 的人都應該有所耳聞,其是泛型程式設計的基礎。顧名思義,模板就是相當於乙個模子,通過這個模子我們可以做出各種各樣的東西,c 模板就是這樣的一種工具。之所以要在c 中引入模板,就是為了減少c 程式中 的重複工作,達到 的可重用的功能。舉乙個我們常用的例子,比較兩個整型a,...

C 學習筆記之 模板

目錄類模板 模板是泛型程式設計的基礎,泛型程式設計即以一種獨立於任何特定型別的方式編寫 即不具體制定資料型別 模板是建立泛型類或函式的藍圖或公式 include include using namespace std 函式模板實現通用資料型別交換 template t屬於通用資料型別 void my...