版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、精選優(yōu)質(zhì)文檔-傾情為你奉上笨鳥(niǎo)先飛學(xué)編程系列-C+高級(jí)特性之模板當(dāng)我們?cè)絹?lái)越多的使用C+的特性, 將越來(lái)越多的問(wèn)題和事物抽象成對(duì)象時(shí), 我們不難發(fā)現(xiàn):很多對(duì)象都具有共性。 比如 數(shù)值可以增加、減少;字符串也可以增加減少。 它們的動(dòng)作是相似的, 只是對(duì)象的類(lèi)型不同而已。C+ 提供了“模板”這一特性, 可以將“類(lèi)型” 參數(shù)化, 使得編寫(xiě)的代碼更具有通用性。 因此大家都稱模板編程為 “通用編程”或 “泛型編程”。一般而言, 模板分為 函數(shù)模板 和 類(lèi)模板,下面就讓我們分別來(lái)了解一下它們。專心-專注-專業(yè)一、 函數(shù)模板1、 函數(shù)模板的定義和使用定義一個(gè)模板函數(shù)的格式并不復(fù)雜, 如下:template
2、<模板參數(shù)列表>返回類(lèi)型 函數(shù)名(函數(shù)參數(shù)列表) / code .下面, 讓我們來(lái)舉一個(gè)例子來(lái)說(shuō)明 模板函數(shù)的作用和用法(具體代碼見(jiàn) Exp01)。/ 定義一個(gè)函數(shù)模板, 用來(lái)實(shí)現(xiàn)任意類(lèi)型數(shù)據(jù)的相互交換。template <typename T>/ 聲明一個(gè) T 數(shù)據(jù)類(lèi)型, 此類(lèi)型隨 調(diào)用方 類(lèi)型的變化而變化void swap(T& a, T& b) T tmp = a; a = b; b = tmp; 上面的代碼, 說(shuō)明了模板函數(shù)的用法。下面再給出調(diào)用的代碼, 我們看看如何使用這個(gè)函數(shù)模板:int main(int argc, char* argv)
3、int nNum1 = 50; int nNum2 = 30; double dfNum1 = 2.1; double dfNum2 = 3.0; char *pszFirst = "Hello " char *pszSec = "world!" swap <int> (nNum1, nNum2);/ 將swap函數(shù)模板實(shí)例化為 int類(lèi)型的模板函數(shù)再調(diào)用 printf("nNum1 = %d, nNum2 = %drn", nNum1, nNum2); swap<double> (dfNum1, dfNum2
4、); printf("dfNum1 = %f, pszSec = %frn", dfNum1, dfNum2); swap<char *> (pszFirst, pszSec); printf("pszFirst = %s, pszSec = %srn", pszFirst, pszSec);return 0;具體的執(zhí)行結(jié)果如下:我相信,如果你是第一次見(jiàn)到模板的代碼,那你一定也會(huì)像我一樣好奇,這個(gè)功能是怎么實(shí)現(xiàn)的,它是怎么做到讓一段代碼來(lái)兼容各種類(lèi)型的呢?當(dāng)我要反匯編該EXE得時(shí)候,無(wú)意間查看了下編程生成的map文件,讓我看到了如下的內(nèi)容:
5、Address Publics by ValueRva+BaseLib:Object0001:?swapYAXAAH0Z f iExp01.obj0001:?swapYAXAAN0Z f iExp01.obj0001:f0?swapYAXAAPAD0Zf0 f iExp01.obj由此可見(jiàn), 我們編寫(xiě)的void swap(T& a, T& b), 只是一個(gè)“函數(shù)模板”, 要使用它需要先將它實(shí)例化為一個(gè)“模板函數(shù)”(如:swap <int>)。編譯器在編譯此程序的時(shí)候,為每個(gè)調(diào)用此模板的代碼生成了一個(gè)函數(shù)。而且在后期的使用過(guò)程中,更加讓我認(rèn)識(shí)到:a、 函數(shù)模板 并不是
6、函數(shù),它僅在編譯時(shí)根據(jù)調(diào)用此模板函數(shù)時(shí)傳遞的實(shí)參類(lèi)型來(lái)生成具體的函數(shù)體!若 函數(shù)模板沒(méi)有被調(diào)用責(zé)不生成任何代碼也不對(duì)模板代碼作任何語(yǔ)法檢查。b、 在模板類(lèi)型參數(shù)中, 實(shí)參與形參要求嚴(yán)格匹配,它不會(huì)進(jìn)行任何的類(lèi)型轉(zhuǎn)換。c、 對(duì)于函數(shù)模板,我們?cè)谡{(diào)用時(shí)不一定必須先進(jìn)行將它實(shí)例化為一個(gè)函數(shù)也是可以的,編譯器會(huì)自動(dòng)的識(shí)別模板的類(lèi)型。(換句話說(shuō):Exp01中的代碼可以直接使用swap, 而不需要<>)2、 函數(shù)模板的重載當(dāng)編寫(xiě)的一個(gè)模板無(wú)法滿足所有需要的情況時(shí),就需要對(duì)模板進(jìn)行重載(或叫 特例化),例如:我們編寫(xiě)了一個(gè)較大值的模板Max:template <typename T>
7、T* const& Max(T const& a, T const& b) return a < b ? b : a;A、 當(dāng)我們需要傳入兩個(gè)指針類(lèi)型的實(shí)參時(shí),該模板就失效了,需要重載該模板:template <typename T>T* const& Max(T* const& a, T* const& b) return *a < *b ? *b : *a;B、 倘若我們?cè)傩枰容^兩個(gè)字符串大小時(shí),上面兩個(gè)模板都失效了。因?yàn)閏har* 并沒(méi)有提供 operator < 運(yùn)行,我們只能通過(guò)調(diào)用strcmp庫(kù)函數(shù)自己
8、實(shí)現(xiàn)一個(gè)Max模板的特例(見(jiàn)Exp02):const char* Max(const char*& a, const char*& b) return strcmp(a, b) < 0 ? b : a;說(shuō)明:C+模板機(jī)制規(guī)定,如果一個(gè)調(diào)用,即匹配普通函數(shù),又能匹配模板函數(shù)的話,則優(yōu)先匹配普通函數(shù)。因此,當(dāng)我們模板特例化的時(shí)候,會(huì)先匹配特例化的函數(shù)。二、 類(lèi)模板1、 基本概念類(lèi)模板一般應(yīng)用于容器類(lèi)中,使得容器能夠處理各種類(lèi)型的對(duì)象,如(詳見(jiàn)Exp03):struct Node Node( int nData = 0 ) m_nData = nData; m_pPrev =
9、m_pNext = NULL; int m_nData;/ 數(shù)據(jù)元素 Node* m_pPrev;/ 指向上一個(gè)元素的指針 Node* m_pNext;/ 指向下一個(gè)元素的指針;class CDListprivate: int m_nCount; Node* m_pHead; Node* m_pTail; int m_nMessage;public:CDList();virtual CDList();public:int GetLen() constm_nCount;Node* GetHead() constreturn m_pHead;Node* GetTail() constreturn
10、m_pTail;public:bool Change(int nIndex1,int nIndex2);void Release();/增加Node* AddTail( int nData );Node* AddHead( int nData );Node* operator(int nIndex);/刪除bool DeleteNode( int nIndex );void PrintAll();/查找Node* FindNode( int nIndex );對(duì)于這樣的鏈表,其節(jié)點(diǎn)的元素只能存放整型數(shù)據(jù)。如果要想讓此雙向鏈表能夠存放任何一種類(lèi)型的元素,那此時(shí)我們需要的問(wèn)題與函數(shù)模板就一樣了,將
11、此類(lèi)修改成類(lèi)模板,現(xiàn)在先不管類(lèi)模板的寫(xiě)法,讓我們按照函數(shù)模板的方法將類(lèi)修改一下:template <typename T>struct Node Node( T Data ) m_Data = Data; m_pPrev = m_pNext = NULL; Tm_Data; / 通用類(lèi)型的數(shù)據(jù)元素 Node<T>* m_pPrev;/ 指向上一個(gè)元素的指針 Node<T>* m_pNext;/ 指向下一個(gè)元素的指針;這樣,我們每個(gè)節(jié)點(diǎn)都可以使用通用的類(lèi)型了,當(dāng)然,對(duì)節(jié)點(diǎn)的處理也一樣得處理。按照這個(gè)樣子將類(lèi)型參數(shù)化(為節(jié)省篇幅,具體的實(shí)現(xiàn)部分請(qǐng)參考Exp04)
12、:template <typename T>class CDListprivate:int m_nMessage;/ 消息號(hào)int m_nCount;/ 鏈表中 元素的數(shù)量Node<T>*m_pHead;/ 鏈表頭指針Node<T>*m_pTail;/ 鏈表尾指針public:CDList();virtual CDList();public:int GetLen() constm_nCount;Node<T>* GetHead() constreturn m_pHead;Node<T>* GetTail() constreturn m
13、_pTail;public:bool Change(int nIndex1,int nIndex2);void Release();/增加Node<T>* AddTail( T Data );Node<T>* AddHead( T Data );Node<T>* operator(int nIndex);/刪除bool DeleteNode( int nIndex );void PrintAll();/查找Node<T>* FindNode( int nIndex );這樣就修改好了,很簡(jiǎn)單吧,貌似類(lèi)模板沒(méi)有什么太多的新語(yǔ)法規(guī)范。完整的模板代碼,
14、大家可以參考Exp04,下面我們總結(jié)一下類(lèi)模板的一些語(yǔ)法小細(xì)節(jié)。2、 類(lèi)模板的定義通過(guò)上面的一番修改,我相信你一定對(duì)類(lèi)模板有了一定的了解,下面我們大致的總結(jié)一下類(lèi)模板的定義格式:Template <typename T>Class 類(lèi)名/ code,可以使用模板參數(shù)T來(lái)指定通用的數(shù)據(jù)類(lèi)型。正如上面的Exp04中一樣,我們的模板寫(xiě)好了,但是它不能直接使用,就像函數(shù)模板一樣,我們需要先將模板實(shí)例化成一個(gè)模板類(lèi)才可以使用。在函數(shù)模板中,編譯器會(huì)針對(duì)我們傳遞的實(shí)參類(lèi)型等信息自動(dòng)的給我們實(shí)例化函數(shù)模板為模板函數(shù),但是類(lèi)模板就沒(méi)有這么智能了,必須手工實(shí)例化:int main(int argc,
15、 char* argv)CDList<int> MyList;/ 將CDList實(shí)例化為一個(gè)int類(lèi)型,也就是說(shuō)鏈表中數(shù)據(jù)元素為整型/(20) (80) 100 200 50 60MyList.AddTail(20);MyList.AddTail(80);MyList.AddTail(100);MyList.AddTail(200);MyList.AddTail(50);MyList.AddTail(60);MyList.PrintAll();MyList.Change(0,1);MyList.PrintAll();return 0;程序執(zhí)行結(jié)果:總結(jié):a、 類(lèi)模板 同樣也不是類(lèi),
16、它僅在編譯時(shí)根據(jù)實(shí)例化本模板時(shí)傳遞的實(shí)參來(lái)生成具體的類(lèi)代碼!若 類(lèi)模板沒(méi)有被實(shí)例化也沒(méi)有被調(diào)用,那編譯器不會(huì)為本模板生成任何代碼也不對(duì)模板代碼作任何語(yǔ)法檢查。3、 類(lèi)模板的特化類(lèi)模板的特化又被叫做類(lèi)模板的定做,首先讓我們來(lái)了解下什么叫作定做。通過(guò)上面幾個(gè)小節(jié)的學(xué)習(xí),我相信,大家都知道模板不能直接被使用:必須先給模板傳遞一個(gè)實(shí)參,將它實(shí)例化為一個(gè)模板類(lèi),然后才可以用它來(lái)定義具體的對(duì)象。這樣就隱含了一個(gè)問(wèn)題:我們通過(guò)給模板傳遞一個(gè)實(shí)參來(lái)實(shí)例化的模板類(lèi)中的代碼都是在模板中定義好的,如果我們不能用與定義好的模板代碼來(lái)生成模板類(lèi),這時(shí)就需要使用模板的特化,也就是“定做”。比如,我們剛才寫(xiě)好的雙向鏈表模板
17、中,對(duì)于某一個(gè)類(lèi)(比如CStudent)來(lái)說(shuō),不允許添加重復(fù)的節(jié)點(diǎn),但是對(duì)于像普通的int,double等數(shù)據(jù)類(lèi)型以及其它一些類(lèi)時(shí),又不需要有這類(lèi)的限制。這時(shí)我們就需要將此雙向鏈表模板針對(duì)這個(gè)不允許有重復(fù)節(jié)點(diǎn)的類(lèi)(如:CStudent)進(jìn)行特化,大致代碼如下:template <>class CDList<CStudent>private:int m_nMessage;/ 消息號(hào)int m_nCount;/ 鏈表中 元素的數(shù)量Node<CStudent>*m_pHead;/ 鏈表頭指針Node<CStudent>*m_pTail;/ 鏈表尾指針p
18、ublic:bool Change(int nIndex1,int nIndex2);void Release();/增加Node<CStudent>* AddTail( CStudent Data );Node<CStudent>* AddHead( CStudent Data );Node<CStudent>* operator(int nIndex);/刪除bool DeleteNode( int nIndex );void PrintAll();/查找Node<CStudent>* FindNode( int nIndex );Node&
19、lt;CStudent>* CDList<CStudent>:AddTail( CStudent Data )Node<CStudent>* pNewNode = new Node<CStudent>(Data);if ( m_pTail )m_pTail->m_pNext = pNewNode;pNewNode->m_pPrev = m_pTail;if ( m_pTail = NULL )m_pHead = pNewNode;m_pTail = pNewNode;m_nCount+;return pNewNode;由此可知,為CStud
20、ent類(lèi)定做的CDList模板類(lèi),就是以CDList<CStudent>為類(lèi)名重寫(xiě)一份CDList<CStudent>實(shí)現(xiàn)而拋棄編譯器為我們生成的CDList<CStudent>類(lèi)。當(dāng)一個(gè)模板擁有多個(gè)模板參數(shù)時(shí),如果我們只對(duì)其部分參數(shù)定做則稱為“局部定做”,這樣定做出來(lái)的“物件”仍然是一個(gè)模板,因?yàn)槲覀冎惶鼗艘徊糠帜0鍏?shù).說(shuō)明:剛才,我們?yōu)镃Student類(lèi)定做的CDList模板類(lèi),其實(shí)我們沒(méi)有必要將整個(gè)CDList<CStudent>類(lèi)都寫(xiě)一遍,只需要重寫(xiě)Add函數(shù)即可,例如:Template<>CDList<CStude
21、nt>:Add(CStudent& n)當(dāng)然,這樣的代碼,需要寫(xiě)在Cpp文件中,并在.h文件中聲明。三、 模板程序的組織當(dāng)然,如果你足夠細(xì)心,你一定會(huì)好奇,為什么我給的例子中,模板的代碼都寫(xiě)在頭文件中(.h文件),這里我們就討論模板代碼的組織方式。C+支持兩種模板代碼的組織方式,分別是包含方式(我們使用的就是包含方式)和分離方式。這兩種組織方式?jīng)]有太根本的區(qū)別,就是一個(gè)將代碼全寫(xiě)在頭文件中,分離方式是像寫(xiě)類(lèi)一樣聲明和定義分別寫(xiě)在頭文件(.h文件)和實(shí)現(xiàn)文件(cpp文件)中。下面我們分別討論下這兩種代碼組織方式。1、 包含方式本專題中,所有的實(shí)例代碼中的模板代碼都是以包含方式組織的
22、。因?yàn)楹枚嗟木幾g器(如VC6的cl)并不支持分離方式組織代碼,將代碼寫(xiě)在頭文件也只是方便編譯器的預(yù)處理工作能方便的將.h文件中的代碼根據(jù)模板實(shí)參的類(lèi)型生成相應(yīng)的模板類(lèi)。當(dāng)然,將代碼都寫(xiě)在頭文件中還有一點(diǎn)點(diǎn)小要求:A、 如果模板的成員函數(shù)寫(xiě)在類(lèi)外,則需要寫(xiě)成如下樣式(見(jiàn)Exp04):template <typename T>/ 每個(gè)類(lèi)外成員函數(shù)前都要有這句N(xiāo)ode<T>* CDList<T>:AddTail( T Data )Node<T>* pNewNode = new Node<T>(Data);if ( m_pTail )m_pT
23、ail->m_pNext = pNewNode;pNewNode->m_pPrev = m_pTail;if ( m_pTail = NULL )m_pHead = pNewNode;m_pTail = pNewNode;m_nCount+;return pNewNode;B、 對(duì)于特化的代碼則需要在.h文件中聲明并在.cpp文件中定義,如果都寫(xiě)在.h文件中編譯會(huì)報(bào)重定義錯(cuò)誤。2、 分離方式上面已經(jīng)提到過(guò),所謂的分離方式組織代碼,就是將模板的聲明和定義分別寫(xiě)在頭文件(.h文件)和實(shí)現(xiàn)文件(cpp文件)中,需要注意的是,并不是所有的編譯器都支持這種寫(xiě)法,目前我只知道GCC支持這種寫(xiě)法。當(dāng)然,分離方式組織代碼也有個(gè)小要求,就是在模板的聲明和定義的template關(guān)鍵字前都加上export關(guān)鍵字。比如:/ .h 頭文件中export template <typename T>class CDListpublic:CDList();virtual CDList();public:bool Change(int nIndex1,int nIndex2);void Release();/增加Node<T>* AddT
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 江蘇省宿遷市沭陽(yáng)縣2024-2025學(xué)年三年級(jí)上學(xué)期期末學(xué)情檢測(cè)數(shù)學(xué)試題參考答案
- 工業(yè)用紙包裝、復(fù)合塑料包裝和新材料生產(chǎn)建設(shè)項(xiàng)目可行性研究報(bào)告寫(xiě)作模板-申批備案
- 2025年度3個(gè)合伙人聯(lián)合開(kāi)發(fā)環(huán)保項(xiàng)目合作協(xié)議書(shū)3篇
- 2025年度123法律APP下載與法律知識(shí)庫(kù)訂閱合同3篇
- 2024第三方房屋抵押擔(dān)保合同
- 2024鋼管架搭設(shè)施工合同
- 2025廠區(qū)綠化養(yǎng)護(hù)與生態(tài)修復(fù)技術(shù)培訓(xùn)服務(wù)合同3篇
- 2024版水電暖承包合同范本
- 2024食品廠員工勞動(dòng)合同簽訂與解除程序合同3篇
- 2024高速公路路側(cè)廣告投放合同
- PDCA在靜脈留置針規(guī)范管理中的應(yīng)用
- (完整)中國(guó)象棋教案
- 熱工自動(dòng)化系統(tǒng)檢修運(yùn)行維護(hù)規(guī)程
- 2023年八年級(jí)物理實(shí)驗(yàn)報(bào)告單
- 顱內(nèi)壓增高病人的護(hù)理
- 裝配式混凝土建筑構(gòu)件識(shí)圖-疊合板識(shí)讀(裝配式混凝土建筑)
- 鑲嵌式電力調(diào)度模擬屏通用技術(shù)條件
- 新流動(dòng)資金測(cè)算表(帶公式)
- GB/T 29076-2021航天產(chǎn)品質(zhì)量問(wèn)題歸零實(shí)施要求
- GB/T 10801.1-2021絕熱用模塑聚苯乙烯泡沫塑料(EPS)
- 行政單位采購(gòu)實(shí)施和驗(yàn)收結(jié)算子流程圖模板
評(píng)論
0/150
提交評(píng)論