C++程序設(shè)計課件 模板_第1頁
C++程序設(shè)計課件 模板_第2頁
C++程序設(shè)計課件 模板_第3頁
C++程序設(shè)計課件 模板_第4頁
C++程序設(shè)計課件 模板_第5頁
已閱讀5頁,還剩49頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

2023/1/1211

第五章模板2023/1/1222intmin(inta,intb){ returna<b?a:b;}doublemin(doublea,doubleb){ returna<b?a:b;}需要為每一種數(shù)據(jù)類型定義一個min函數(shù)例:求兩個數(shù)的最小值參數(shù)個數(shù)、處理流程相同2023/1/1233?min(?a,?b){ returna<b?a:b;}函數(shù)參數(shù)類型或返回類型能否在函數(shù)定義時不明確指定,當調(diào)用時根據(jù)實參再確定?5.1函數(shù)模板2023/1/1244template

<classType>Typemin(Typea,Typeb){ returna<b?a:b;}5.1.1函數(shù)模板定義:將函數(shù)參數(shù)類型或返回類型參數(shù)化關(guān)鍵字template總是放在模板的定義與聲明的最前面;關(guān)鍵字后面是用逗號分隔的模板參數(shù)表,它用尖括號<>括起來;每個模板類型參數(shù)由關(guān)鍵字class或typename開頭,參數(shù)名是用戶自定義的標識符。template

<typenameParm>Parmmin(Parm

a,Parm

b){ returna<b?a:b;}等同于2023/1/1255template

<classType>Typemin(Typea,Typeb){ returna<b?a:b;}voidmain(){ intri=min(10,20); doublerd=min(10.2,20.1);}//intmin(int,int);//doublemin(double,double);模板實例化2023/1/1266template<classT1,classT2,classT3>T1sum(T2a,T3b){

T1s; s=a+b; returns;}模板類型參數(shù)在模板定義中的使用方式和一般類型相同注意:函數(shù)參數(shù)類型可以被部分參數(shù)化,但模板參數(shù)表不能為空。2023/1/1277例:求一數(shù)組中的最小值。intmin(constintarray[10]){ intmin_val=array[0]; for(inti=1;i<10;i++) if(array[i]<min_val) min_val=array[i]; returnmin_val;}intmin(constintarray[],intsize){ intmin_val=array[0]; for(inti=1;i<size;i++) if(array[i]<min_val) min_val=array[i]; returnmin_val;}template<classType>Type

min(constType

array[],intsize){

Type

min_val=array[0]; for(inti=1;i<size;i++) if(array[i]<min_val) min_val=array[i]; returnmin_val;}2023/1/1288注意:模板參數(shù)可以是一個模板類型參數(shù),它代表了一種類型;也可以是一個模板非類型參數(shù),模板非類型參數(shù)由一個普通的參數(shù)聲明構(gòu)成,它代表了一個常量表達式。intmin(constint(&r_array)[10]){ intmin_val=r_array[0]; for(inti=1;i<10;++i) if(r_array[i]<min_val) min_val=r_array[i]; returnmin_val;}template<classType,intsize>Typemin(constType(&r_array)[size]){ Typemin_val=r_array[0]; for(inti=1;i<size;++i) if(r_array[i]<min_val) min_val=r_array[i]; returnmin_val;}2023/1/1299template<classType,intsize>Typemin(constType(&r_array)[size]);用函數(shù)實參的類型來決定模板實參的類型和值的過程被稱為模板實參推演。(函數(shù)返回類型并不用于模板實參推演)voidmain(){ intai[]={12,7,9,39,3}; doublead[3]={2.3,4.5,1.8}; inti=min(ai); doubled=min(ad); inta=min(ad);}5.1.2函數(shù)模板實例化//Type為int,size為5//Type為double,size為3//Type為double,size為32023/1/121010template<classT1,classT2,classT3>T1sum(T2a,T3b){

T1s; s=a+b; returns;}chara=‘0’;inti=1;charb=sum(a,i);charsum(char,int);?charc=sum<char,char,int>(a,i);顯式模板實參,可省略尾部模板實參chard=sum<char>(a,i);//省略T2,T32023/1/1211115.1.3模板編譯模式我們把函數(shù)模板定義放在哪里?放在頭文件中,就好像對內(nèi)聯(lián)函數(shù)定義的做法一樣,在使用函數(shù)模板實例的地方包含它們;或者我們只在頭文件中給出函數(shù)模板聲明,而把模板定義放在*.c中,就好像對非內(nèi)聯(lián)函數(shù)的做法一樣。C++支持兩種模板編譯模式:包含模式和分離模式。2023/1/121212包含編譯模式:將整個模板定義放在頭文件中。//model1.htemplate<classType>Typemin(Typet1,Typet2){ returnt1<t2?t1:t2;}//在使用模板實例之前包含模板定義#include"model1.h"inti,j;doubledobj=min(i,j);缺點:向用戶暴露了模板實現(xiàn)細節(jié)2023/1/121313分離編譯模式: 函數(shù)模板的聲明被放在頭文件中, 實現(xiàn)放在*.c文件中。//model2.htemplate<classType>Typemin(Typet1,Typet2);//model2.Cexporttemplate<classType>Typemin(Typet1,Typet2){

……

}//user.C#include"model2.h"inti,j;doubled=min(i,j);template之前加上關(guān)鍵字export來聲明一個可導(dǎo)出的函數(shù)模板,export不需要出現(xiàn)在頭文件的模板聲明中2023/1/121414例:定義一個隊列類classQueue{public: Queue():front(0),back(0){} ~Queue();

int&remove(); voidadd(constint&); boolis_empty()const{ returnfront==0; }private: QueueItem*front; QueueItem*back;};classQueueItem{public: QueueItem(constint&);private:

intitem; QueueItem*next;};能否定義通用隊列類:不限制結(jié)點保存的數(shù)據(jù)類型?2023/1/1215155.2類模板template<classType>classQueueItem{public: QueueItem(constType&);private:

Typeitem; QueueItem*next;};將類定義中用到的數(shù)據(jù)類型或常量值參數(shù)化2023/1/121616template<classType>classQueue{public: Queue():front(0),back(0){} ~Queue();

Type&remove(); voidadd(constType&); boolis_empty()const{ returnfront==0; }private: QueueItem<Type>*front; QueueItem<Type>*back;};類模板實例化2023/1/121717注意:函數(shù)模板實例化時,既可以提供顯式模板實參,也可根據(jù)函數(shù)實參進行實例化;類模板無法根據(jù)上下文環(huán)境確定模板參數(shù),所以必須提供顯式模板實參進行實例化。Queue<int>qi;Queue<string>qs[100];Queue<double>*qp=newQueue<double>;實例化后的類模板稱為模板類,其使用方法與一般類相同2023/1/121818類模板成員函數(shù)定義:在類模板定義之外template<classType>voidQueue<Type>::add(constType&val){ QueueItem<Type>*pt= newQueueItem<Type>(val); if(is_empty()) front=back=pt; else { back->next=pt; back=pt; }}當類模板被實例化時,類模板的成員函數(shù)并不自動被實例化,只有當一個成員函數(shù)被程序用到函數(shù)調(diào)用或取地址時,它才被實例化。Queue<int>qi;inta;…………qi.add(a);2023/1/121919類模板編譯模式:包含編譯模式:類模板定義和成員函數(shù)定義等都放在頭文件中。分離編譯模式:類模板定義放在頭文件中,成員函數(shù)等定義放在程序文本文件*.cpp中。//-----Queue.h-----exporttemplate<classType>classQueue{ ...public: Type&remove(); voidadd(constType&); ....};//-----Queue.C-----#include"Queue.h"template<classType>voidQueue<Type>::add( constType&val){...}template<classType>Type&Queue<Type>::remove(){...}export關(guān)鍵字用作類模板定義中2023/1/1220205.3STL(標準模板庫:

StandardTemplateLibrary)各種各樣的數(shù)據(jù)結(jié)構(gòu):鏈表、堆棧、隊列、向量……各種各樣的操作:遍歷、插入、刪除、替換……面向?qū)ο蟮淖畲蠛锰帲簭?fù)用、復(fù)用、再復(fù)用C++標準庫提供許多復(fù)用組件2023/1/122121STL包括三個主要組件:容器(container):模板化的復(fù)雜數(shù)據(jù)類型;迭代器(iterator):用于迭代訪問容器中的數(shù)據(jù);泛型算法(gernericalgorithm):可應(yīng)用在多種數(shù)據(jù)類型(包括容器類型或內(nèi)置數(shù)據(jù)類型)上的公共操作。下面以vector容器為例介紹容器、迭代器、泛型算法的使用2023/1/1222225.3.1順序容器:vector類模板:模板參數(shù)表示所存儲每個元素的數(shù)據(jù)類型快速隨機訪問任何元素在尾部快速插入、刪除元素,在其它位置插入、刪除元素效率很低動態(tài)增長:存儲空間的申請和釋放由vector類負責vector類表示具有連續(xù)內(nèi)存單元的數(shù)據(jù)結(jié)構(gòu):順序容器:由單一類型元素組成、順序存放的一個集合:vector、list、deque2023/1/122323為了定義vector對象,必須包含庫頭文件:#include<vector>usingnamespacestd;容器對象的定義以容器類型的名字開始,后面是所包含的元素的實際類型,例如:vector<int> ivec;vector<string> svec;可以是各種內(nèi)置數(shù)據(jù)類型或用戶自定義類初始為空:長度為0用戶自定義類必須支持以下操作:元素類型必須支持等于操作符元素類型必須支持小于操作符元素類型必須支持拷貝構(gòu)造函數(shù)2023/1/122424插入元素最簡單的方法是push_back(),將元素插入在容器的尾部:vector<string>svec;stringtext_word;while(cin>>text_word){

svec.push_back(text_word);

cout<<svec.size()<<endl;}長度動態(tài)增長vector支持其它一些操作:比較操作指定位置或范圍的插入、刪除操作……2023/1/122525迭代器:指向容器中的元素,用于對順序或關(guān)聯(lián)容器類型中的每個元素進行連續(xù)訪問。5.3.2迭代器(iterator)預(yù)定義迭代器 ++方向 功能iterator 向前 讀/寫const_iterator 向前 讀reverse_iterator 向后 讀/寫const_reverse_iterator 向后 讀vector中定義的迭代器:vector<string>::iteratorvector<int>::iterator2023/1/122626vector<string>vec;vector<string>::iteratoriter=vec.begin();vector<string>::iteratoriter_end=vec.end();for(;iter!=iter_end;++iter) cout<<*iter<<endl;begin()返回一個iterator:它指向容器的第一個元素end()返回一個iterator:它指向容器的末元素的下一個位置迭代器可進行比較、自增/自減、解尋址等操作2023/1/122727const_iterator

允許以只讀方式訪問容器的底層元素例如#include<vector>voideven_odd(constvector<int>*pvec,vector<int>*pvec_even, vector<int>*pvec_odd){ vector<int>::const_iteratorc_iter=pvec->begin(); vector<int>::const_iteratorc_iter_end=pvec->end(); for(;c_iter!=c_iter_end;++c_iter) if(*c_iter%2) pvec_odd->push_back(*c_iter); else pvec_even->push_back(*c_iter);}2023/1/122828可以用標量算術(shù)運算使iterator從當前位置偏移到某個位置上:vector<int>::iteratoriter=vec.begin()+vec.size()/2;將iter指向vec的中間元素,而iter+=2;將iter向前移動兩個元素容器對象也可以用“由一對iterator標記的起始元素和末元素下一位置之間的拷貝”來初始化:vector<string>svec;//...//用svec的全部元素初始化svec2vector<string>svec2(svec.begin(),svec.end());//用svec的前半部分初始化svec3vector<string>::iteratorit=svec.begin()+svec.size()/2;vector<string>svec3(svec.begin(),it);2023/1/122929在迭代器的支持下,vector等容器類提供檢索、插入、刪除元素等獨有操作。另外還有一些操作,如:查找、排序、合并等操作,這些操作不是由每個容器類單獨提供的,而是作為各種容器類、內(nèi)置數(shù)組類型都需要的公共操作抽取出來,形成一個通用的算法集合,由庫函數(shù)提供。5.3.3泛型算法泛型算法:STL提供了70種左右的算法2023/1/123030為了使用泛型算法,必須包含庫頭文件:#include<algorithm>intia[6]={0,1,2,3,4,5};vector<string>svec;//……vector<string>::iteratorviter;int*pia;inti=3;stringstr=“hello”;pia=find(&ia[0],&ia[6],i);viter=find(svec.begin(),svec.end(),

str);所有泛型算法兩個實參都是一對iterator,它們標記出要操作的容器或內(nèi)置數(shù)組中的元素范圍可應(yīng)用在各種容器類型或內(nèi)置數(shù)組類型上2023/1/123131#include<iostream>voidmain(){ cout<<“Helloworld!"; charstr[20]; cin>>str;}深入:輸入、輸出流2023/1/123232<iostream>庫中提供了以下類的定義:

istream類 (輸入流)

ostream類 (輸出流)

iostream類 (派生自istream和ostream,輸入/輸出流)同時該庫定義了如下對象:cin: istream類對象,代表標準輸入;cout: ostream類對象,代表標準輸出;cerr: ostream類對象,代表標準錯誤輸出。2023/1/123333輸出: 重載的左移操作符 <<輸出操作符可以接受任何內(nèi)置數(shù)據(jù)類型的實參;可以連續(xù)輸出多個數(shù)據(jù)。能否輸出類對象的信息?classPerson{public:

……private: char*name; intage;}ostream&operator<<(ostream&out);friendostream&operator<<(ostream&out,Person&one);2023/1/123434ostream&operator<<(ostream&out,Person&one){ out<<<<“\t”<<one.age; returnout;}Person li,wang,zhang;……cout<<li<<wang<<zhang;2023/1/123535輸入: 重載的右移操作符 >>注意:當右操作數(shù)與實際輸入數(shù)據(jù)類型不一致時,讀入失敗,返回false。比輸出更容易出錯。缺省情況下,以空格、換行、制表符作為分隔符,并丟棄掉。intivalue;cin>>ivalue; //當輸入小數(shù)或字符串時便出錯if(cin>>ivalue)

……2023/1/123636charch;while(cin>>ch) ;abcd//忽略空格和換行符//讀入四個字符操作符noskipws使輸入操作符不跳過空白字符:charch;cin>>noskipws;while(cin>>ch);cin>>skipws;//讀入七個字符2023/1/1237372023/1/1238382023/1/1239392023/1/124040其它的輸入/輸出操作:

istream成員函數(shù):

get() getline() read() peek()

…… ostream成員函數(shù):

put() write()2023/1/124141下列三種類類型提供了文件支持ifstream

從istream派生,把一個文件綁到程序上,用來輸入ofstream

從ostream派生,把一個文件綁到程序上,用來輸出fstream

從iostream派生,把一個文件綁到程序上用來輸入和輸出。為了使用文件流組件,我們必須包含相關(guān)的頭文件#include<fstream>由于在fstream頭文件中也包含了iostream頭文件,所以我們不需要同時包含這兩個文件深入:文件操作2023/1/124242為了打開一個僅被用于輸出的文件,我們可以定義一個ofstream類對象,例如ofstreamoutfile("copy.out",ios_base::out);注意:輸出模式ios_base::out或附加模式ios_base::app,缺省為輸出模式;ofstream從ostrearn類派生,所以所有ostream操作都可以應(yīng)用到一個ofstream類對象上。outfile<<“hello,world”<<endl;為了打開一個僅用于輸入的文件,我們可以使用ifstream類對象,例如:ifstreaminfile(“input.txt”);2023/1/124343在定義ifstream和ofstream類對象時,我們也可以不指定文件,以后可以通過成員函數(shù)open()顯式地把一個文件連接到一個類對象上,例如ifstreamcurFile;curFile.open(“input.txt”);我們可以通過成員函數(shù)close()斷開一個文件與程序的連接,例如curFile.close();2023/1/124444fstream類對象可以打開一個被用于輸出或者輸入的文件,例如:

fstreamio("word.out",ios_base::in|ios_base::app);seekg()或seekp()成員函數(shù)分別用于定位讀、寫位置。2023/1/124545classiStack{public: …… boolpop(int&top_value); boolpush(intvalue); boolfull(); boolempty(); ……};intvalue;iStackst;……if(!st.push(value)) cout<<“Full”;……if(!st.pop(value)) cout<<“Empty”;……if(!st.push(value))

……錯誤處理和正常操作混在一起深入:異常(Exception)處理2023/1/124646異常是程序可以檢測到的、運行時刻不正常的情況異常處理定義:定義異常類型拋出異常捕獲異常處理異常2023/1/124747拋出異常:

throw

異常對象;異常類型的一個實例classiStack{public://不再返回一個值voidpop(int&value);voidpush(intvalue);……}#include“stackError.h”voidiStack::push(intvalue){ if(full()) { StackErrorerror(1,value);

throwerror; }

……}throwStackError(1,value);執(zhí)行throw語句后,便拋出一個異常,程序?qū)膾伋霎惓N恢猛顺?023/1/124848捕獲和處理異常:try{ //包含throw語句

……}catch(異常類型1[對象]){ //處理一種異常

……}catch(異常類型2[對象]){ //處理另一種異常

……}throw語句必須在try塊中。如果throw拋出的異常對象類型與catch后括號內(nèi)的異常類型一致,則程序執(zhí)行該catch后的子句2023/1/124949try{intvalue;iStackst;……st.push(value);……st.pop(value);……st.push(value);……}catch(StackErrorerr){ intst=err.state(); if(st==1)

…… elseif(st==2)

…… else

……}正常操作與錯誤處理操作的分離2023/1/125050異常處理步驟:try塊中如果沒有異常拋出,則正常執(zhí)行,并忽略后面的catch子句。若try塊中有異常拋出,則程序從拋出位置退出;若拋出的異常對象類型與try塊后的某個catch聲明類型匹配,則執(zhí)行該catch子句處理異常;處理完異常后,程序?qū)腸atch子句列表后的語句繼續(xù)執(zhí)行。若找不到匹配項,則該函數(shù)帶著一個異常退出,繼續(xù)檢查函數(shù)調(diào)用點是否有try/catch子句。boolbuidStack(){ try{ //push操作

…… } catch

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論