




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第五章,模 板,主要內容,模板的概念 函數模板和模板函數 類模板和模板類,5.1 模板的概念,引例: int max( int x, int y) return (xy) ? x: y; double max( double x, double y) return (xy) ? x: y; char max( char x, char y) return (xy) ? x: y; ,可以看出,這些函數版本的功能都是相同的,只是參數類型和函數返回類型不同。 那么能否為這些函數只寫出一套代碼呢?,C+解決這個問題的一個方法就是使用模板。,利用模板機制可以顯著減少冗余信息,能大幅度地節(jié)約程序代碼,進
2、一步提高面向對象程序的可重用性和可維護性 模板概念是對類屬概念的繼承與發(fā)展。,類屬,類屬是 一種參數多態(tài)的機制。 ALGOL68語言最先引入類屬(genericity)的概念,最主要的類屬形式是類型參數化,即用一個或多個類型去參數化一個軟件元素。 基本思想: 在實際工作中人們經常用到剛才那樣一些程序模塊,從它們的邏輯功能(或實現算法)看,彼此是相同的,所不同的主要是處理對象(數據)的類型。 如果提供具有相同邏輯功能的程序正文(保存共性),然后把數據類型作為參數傳遞(指出不同特性),則可節(jié)約大量程序代碼,這就是類屬機制的思想,又稱為參數化模板。,類屬又可分為無約束類屬機制和約束類屬機制 無約束類
3、屬機制是指對作為類屬參數的數據類型沒有任何特殊要求 約束類屬機制則意味著對類屬參數有明確要求,只有在類屬實參滿足一定條件時才有意義。 1. 無約束類屬的例子 void swap(T ,2. 約束類屬的例子 T minimum(T x,T y) if(x=y) return x; else return y; 并不是任何數據類型都可以作為這個函數的類屬實參,只有滿足一定條件(即定義了“=”操作)的數據類型,才能作為這個函數的類屬實參。 /結構變量的比較運算與整型變量的比較運算就有很大差別 C+語言使用模板來實現類屬機制。,在C+中,模板是實現代碼重用機制的一種工具,它可以實現類型參數化,即把類型
4、定義為參數,從而實現代碼的可重用性。 C+程序由類和函數組成,C+中的模板也分為類模板和函數模板。 例: T max( T x, T y) return (xy) ? x : y; ,1. 模板的概念,這個以參數化表示的函數稱為函數模板。,所謂函數模板,實際上是建立一個通用函數,其函數類型和形參類型不具體指定,用一個虛擬的類型(如:T)來代替,這個通用函數就稱為函數模板。 3. 模板函數 在定義了一個函數模板后,當編譯系統發(fā)現有一個對應的函數調用時,將根據實參中的類型來確認是否匹配函數模板中對應的形參,然后生成一個重載函數,該函數的定義與函數模板的函數定義體相同,稱之為模板函數。,2. 函數模
5、板,比較:函數模板和模板函數的區(qū)別,函數模板是模板的定義,定義中用到通用類型參數。 模板函數是實實在在的函數定義,它由編譯系統在遇到具體函數調用時所生成,具有程序代碼。,同樣,類模板是模板的定義,不是一個實實在在的類,其定義也用到通用類型參數。在定義了一個類模板后,可以創(chuàng)建類模板的實例,即生成模板類。,4. 模板、模板函數、模板類和對象之間的關系,說明:,由于模板的作用是使程序能夠對不同類型的數據進行相同方式的處理,因此,在進行相同方式的處理時,只有當參加運行的數據類型不同時,才可以定義模板。,5.2 函數模板和模板函數,函數模板的定義和模板函數的生成 1) 定義函數模板的一般形式: temp
6、late 函數返回值類型 函數名(形參表) /函數體 ,例:將求最大值的函數max()定義成函數模板。,template /模板聲明 T max(T x, T y) /模板定義體 return (xy) ? x:y; 其中,T是模板形參,它既可以取系統預定義的數據類型,也可以取用戶自定義的類型。,2) 模板函數的生成:,定義了函數模板后,程序中并沒有得到真正的函數代碼。只有用一個具體的數據類型來代替上面的類型參數T以后,即將模板具體化后,系統才會生成特定于具體數據類型的程序代碼(模板函數)。,當程序中有如下語句時, int i; i=max(2, 30); 編譯系統就會自動生成具有整型參數和返
7、回值的函數代碼: int max( int x, int y) return (xy) ? x: y; 然后將它插入到程序中,這個生成的函數稱為模板函數。這樣,如果再有一句對整型參數的函數調用,系統就不會再次生成函數代碼,而是直接使用已經生成的函數代碼了。,例:,同樣,如果程序中又有了這么一句函數調用: double x=max(12.3,48.5); 編譯系統會先看有沒有已經從模板生成了函數代碼,如果沒有,就生成具有雙精度浮點型參數的函數代碼: double max(double x , double y) return (xy)?x:y; ,說明:,一般來說,當編譯程序看到對模板函數的調用
8、語句時,就會根據函數模板生成對應于該特定數據類型的具體函數代碼。 但是,也可以通過聲明函數原型來告訴編譯程序實例化函數模板。例如: float max(float,float); 當編譯器看到函數原型時,會先根據函數模板生成相應的函數代碼。,例:見下例exec11.1。,例exec11-1 不同數據類型數組中的元素求和,#include using namespace std; template T Sum(T *array,int size=0) T total=0; for (int i=0;isize;i+) total+=arrayi; return total; int main()
9、 int int_array=1,3,5,7,9,11,13,15,17,19; double double_array=1.1,2.2,3.3,4.4,5.5,6.6,5.7,8.8,9.9,10.01; coutThe summary of integer array are Sum(int_array,10)endl; coutThe summary of double array are Sum(double_array,10)endl; return 0; ,在程序中,生成了兩個模板函數: Sum(int_array,10)用實參int_array將類型參數T進行了實例化,int_a
10、rray為一整型數組名,編譯程序生成一個形如int Sum(int *array,int size)的模板函數; Sum(double_array,10)用實參double_array將類型參數T進行了實例化,double_array為一雙精度型數組名,編譯程序生成一個形如double Sum(double *array,int size)的模板函數。,2. 函數模板的使用,雖然函數模板中的模板形參T可以實例化為各種類型,但實例化T時,虛實參之間必須保持完全一致的類型。模板類型并不具有隱式的類型轉換,例如在int與char之間、float與int之間、float與double之間等的隱式類型轉
11、換。 例: 見例exec11.2。,#include using namespace std; template T max(T a,T b) T c; if (ab) c=a; else c=b; return c; int main() int i1=50,i2=40; char c1=A,c2=B; double x1=45.6,x2=2.5e2; coutmax(i1,i2)endl; coutmax(c1,c2)endl; coutmax(x1,x2)endl; coutmax(i1,c1)endl; coutmax(i1,x1)endl; coutmax(c1,x1)endl; r
12、eturn 0; ,分析: 由于這3條語句的實參的類型與形參不一致,而max模板參數T的各實參之間必須保持一致的類型,因此出現編譯錯誤。 例如,max(i1,c1) 系統找不到與max(int, char)相匹配的函數定義。,解決方法:,采用強制類型轉換。 例:將調用語句max(i1, c1)改寫為 max(i1, int(c1) 顯式給出模板實參,強制生成對特定實例的調用。具體地說,就是在調用格式中要插入一個模板實參表。 例: cout(i1,x1)就是模板實參表,通過它通知編譯系統生成對形如int max(int a, int b)的函數實例的調用。這樣,在調用過程中,double型的參數
13、x1將被自動轉換成int型。,例:采用上面兩種方法對例exec11.2進行修改。, int main() int i1=50,i2=40; char c1=A,c2=B; double x1=45.6,x2=2.5e2; cout(i1,x1)(c1,x1)endl; /正確 return 0; ,問題: 比較兩個字符串哪個大,能不能用上面的函數模板直接比較兩個字符指針的大小?,分析: 比較兩個字符指針的大小不能使用上述的方法(因為:s1,s2是指針),而需要用strcmp()函數來進行。因此,需要重新定義max()來比較兩個字符串。 那么怎樣利用函數模板來實現這一目的呢?,max(s1,s2
14、),解決方法: 允許函數模板參與重載,即允許用普通函數重載一個同名的函數模板。 有以下兩種重載方式: 與函數模板共享函數體; 重新定義函數體。,與函數模板共享函數體,通過借用函數模板的函數體來定義重載函數模板的非模板函數。 例: template T max(T a,T b) T c; if (ab) c=a; else c=b; return c; int max(int, int); /與函數模板共享函數體,void f(int i,char c) int x; x=max(i,i); x=max(c,c); x= max(i,c);/調用int max(int,int); x=max(c
15、,i); /調用int max(int,int); 因為普通函數具有隱式類型轉換能力,所以不出錯!,重新定義函數體,在定義重載函數模板的非模板函數時,給出這個重載的非模板函數的函數體。 例: 見例exec11.4。 說明: 編譯程序在處理這種情況時, 首先尋找參數完全匹配的普通函數; 然后再尋求參數完全匹配的函數模板; 最后尋求低一級的對函數的重載方法(類型轉換達到匹配)。,char * max(char *a,char *b) if (strcmp(a,b)0) return a; else return b; ,函數模板總結,函數模板是對一組函數的描述,它不是一個實實在在的函數,編譯系統并
16、不產生任何執(zhí)行代碼。 當編譯系統在程序中發(fā)現有與函數模板中相匹配的函數調用時,便生成一個重載函數,該重載函數的函數體與函數模板的函數體相同。這個根據函數模板生成的重載函數稱為模板函數。,函數模板與模板函數的區(qū)別如下: (1)函數模板不是一個函數,而是一組函數的模板,在定義中使用了參數類型。 (2)模板函數是一種實實在在的函數定義,它的函數體與某個函數模板的函數體相同。 編譯系統遇到模板函數調用時,將生成可執(zhí)行代碼。 函數模板是定義重載函數的一種工具。一個函數模板只為一種原型函數生成一個模板函數,不同原型的模板函數是重載的。這樣就使得一個函數只需編碼一次就能用于某個范圍的不同類型的對象上。 因此
17、,可以說函數模板是提供一組重載函數的樣板。,5.3 類模板和模板類,使用類模板(也稱為類屬類或類生成類)機制,用戶可以為類定義一種模式,使得類中的某些數據成員、某些成員函數的參數和某些成員函數的返回值,可以是任意類型的。 類模板不再代表一個具體的、實際的類,而是代表一類類。,1. 類模板的定義,定義類模板,包含兩方面內容: 定義類; 在類定義體外定義成員函數。 1) 定義類的一般形式: template /模板聲明 class Name /類的定義 ;,例1:向量類模板定義。,template class Vector T *data; int size; public: Vector(int
18、 i) data=new Ti; Vector() delete data; T ,例2:一個單鏈表類模板的定義。,template class List/定義通用單鏈表類模板List,有一個模板參數T public: List(); /聲明構造函數 void Add(T ,2) 在類定義體外定義成員函數,如果在類定義體外定義成員函數時,如果該成員函數中有模板參數,則需先進行模板聲明,而且用類模板名,而不是用類名來限定函數名,即在函數名前的類名后綴上“”。其一般形式為: template 函數返回值類型 類名:成員函數名(形參表) /函數體 ,例:類模板List中成員函數Add()和Remov
19、e()在類體外定義。,template void List:Add(T / 將新結點的地址賦給頭指針 template void List:Remove(T,例:,List intList; 表示將類模板List的類型參數T全部替換成int 型,從而創(chuàng)建一個具體的整型鏈表類,并生成該具體類的一個對象intList。 List charList; 表示將類模板List的類型參數T全部替換成char 型,從而創(chuàng)建一個具體的字符鏈表類,并生成該具體類的一個對象charList。,比較:類模板與模板類的區(qū)別。,類模板是模板的定義,不是一個實實在在的類,定義中用到通用類型參數。 模板類是實實在在的類定義
20、,是類模板的實例化。類定義中參數被實際類型所代替。 例: 見例exec11.5。,3. 類模板的派生,既可以從類模板派生出類模板,也可以派生出普通類(非模板類)。主要有以下幾種形式: 從類模板派生出類模板; 從類模板派生出普通類; 從普通類派生出類模板。,1) 從類模板派生出類模板,從類模板派生出新的類模板的格式如下所示: template class Base ; template class Derived: public Base ; 與定義一般派生類的格式類似,只是在指出它的父類時要加上模板參數。如,Base 。,例:見例exec11.6。,2) 從類模板派生出普通類,從類模板派生出一
21、個普通類的格式如下所示: template class Base ; class Derived: public Base ; 首先,作為新派生出來的普通類的父類,必須是類模板實例化后生成的模板類。例如上面的Base; 其次,在派生類定義之前不需要模板聲明語句template 。,例:見例exec11.7。,3) 從普通類派生出類模板,在聲明一個類模板時,可以盡可能將類模板中與虛擬類型參數無關的成員剝離出來,構成一個普通類,作為類模板的基類。因此,從普通類派生出類模板的情況也是十分常見的。 例: class Base ; template class Derived:public Base T
22、 data; ,模板的派生甚至可以繼承一個未知的基類,也就是說,繼承哪個基類由模板參數決定。 例: 見例exec11.8。,template class Derived:public T public: Derived():T() cout x; Derived y; Derived z; return 0; ,小 結,模板的概念: 是實現代碼重用機制的一種工具,它可以實現類型參數化,即把類型定義為參數,從而實現代碼的可重用性。 模板的分類:函數模板和類模板 函數模板和模板函數 函數模板的定義和使用方法; 函數模板與模板函數的區(qū)別。 類模板和模板類 類模板的定義和使用方法; 類模板與模板類的區(qū)別; 類模板的派生(3種形式)。,思考題:,1已知 void Sort(int a,int size); void Sort(double a,int size); 是一個函數模板的兩個實例,其功能是將數組a中的前size個元素按從小到大順序排列。試設計這個函數模板。,#include using namespace std; template T Sum(T *ar
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 中介服務在創(chuàng)新創(chuàng)業(yè)企業(yè)戰(zhàn)略規(guī)劃中的作用考核試卷
- 醫(yī)療器械生產中信息化學品的質量控制與數據分析應用考核試卷
- 倉儲安全操作人員健康管理考核試卷
- 記賬實操-事業(yè)單位的會計賬務處理分錄
- 機械維修自動化與機器人技術
- 二手房買賣協議書14篇
- 永州支隊團日活動方案
- 漢語團隊教研活動方案
- 歡迎國慶活動方案
- 殘聯宣傳年活動方案
- 算法用戶標簽管理制度
- 《選礦廠安全生產標準化評分辦法》
- 暗夜旅游地光污染治理-洞察及研究
- 2025安徽蚌埠市國有資本運營控股集團有限公司招聘4人筆試參考題庫附帶答案詳解析集合
- 期末試卷(含答案)2024-2025學年四年級下冊數學北師大版
- (2025)輔警招聘考試試題庫附答案詳解(綜合題)
- 《客艙安全與應急處置》-課件:火災的基礎知識
- 自然資源執(zhí)法監(jiān)察工作規(guī)范培訓課件
- 部編版《語文》三年級下冊全冊教案及反思
- 《中華人民共和國職業(yè)分類大典》電子版
- 結構工程師績效考核評分表
評論
0/150
提交評論