第8章 異常,模板_第1頁
第8章 異常,模板_第2頁
第8章 異常,模板_第3頁
第8章 異常,模板_第4頁
第8章 異常,模板_第5頁
已閱讀5頁,還剩50頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1第8章 異常(exception),

模板(template)

2主要內容異常模板函數模板類模板命名空間31.

異常(exception)4C++中錯誤被稱為異常或例外(Exception)。異常是運行時產生的錯誤,是由大量的例外情況產生的,例如內存用盡,不能打開文件,使用不合適的值初始化對象…51.1 異常的引入C語言處理錯誤時,通常返回一個特殊的值,用此值來表示函數產生了一個錯誤。例如:

if(somefunc()==ERROR_RETURN_VALUE) //handletheerrororcallerror-handlerfunction else //proceednormally if(anotherfunc()==NULL) //handletheerrororcallerror-handlerfunction else //proceednormally if(thirdfunc()==0) //handletheerrororcallerror-handlerfunction else //proceednormally

6這種處理的問題是:每調用一次函數,程序就必須檢查一遍返回值,代碼量增多。當在程序中使用類庫時,這個問題變得更加復雜。使得錯誤檢測更加不容易。71.2 異常的語法C++使用try、throw和catch語句實現異常處理。當預測到某段程序將可能出現問題時,則將該段程序放在try語句之后,使該段程序得以有機會拋出異常。8在程序的某個函數中發現異常時使用throw表達式拋出這個異常,這個異常被拋給該函數的調用者。調用者用catch捕捉該異常并進行相應的處理。9C++庫中的一些庫函數已經設計了異常拋出。也就是系統會自動throw一些定義好的異常,以便C++程序里可以catch它們,并進行處理。例:badalloc.cpp10程序里自定義異常,并進行處理方法:#include<iostream.h>classBall{ intradius;public: Ball(intrad);voidprint()const{cout<<radius<<endl;}};11Ball::Ball(intrad){radius=rad;if(radius==0)throwrad;//如果有錯誤,使用 throw拋出一個標識

}12

intmain(){try//把可能出現異常的程序放在try復合語句中

{Ballmyball(1);Ballyourball(0);//exception}catch(int){//對應異常標識,給出相應處理方法

cout<<"exception:invalidradius,radiusmustbegreatthan0"<<endl;}return0;}13C++語言提供對處理異常情況的內部支持。

try{//try關鍵字引導的try塊

……//可能引發錯誤的程序段

……throwlabel1//異常標識

……throwlabel2//異常標識}//結束try塊14

catch(異常類型聲明1)//catch塊與label的類型匹配

{

……//處理響應異常

}

catch(異常類型聲明2)//catch塊與label的類型匹配{

……//處理響應異常}15拋擲異常與異常處理程序之間,是按數據類型的嚴格匹配來捕獲的。下面是幾個throw和catch對應的例子:“throw1;”和“throwi;”被catch(inti)

捕獲“throwdnum”被catch(doublednum)

捕獲“throw"abc";”被catch(char*ptr)

捕獲“throwstring("abc");”被catch(stringstr)

捕獲“throwpoint(1.2,5.8);”被catch(pointa)

捕獲16演示異常的例子。#include<iostream>usingnamespacestd;doubleDiv(doublex,doubley);voidmain(){boolflag=true; try { cout<<Div(15.5,5.5)<<endl; 17cout<<Div(8.25,8.25)<<endl;cout<<Div(70,3.3)<<endl;}//endoftry catch(double) { cout<<"exceptofdevidingzero.\n"; flag=false; } if(flag==false)cout<<"Thereisanymistake."<<endl; elsecout<<"Thatisok.\n"; cout<<"Exit..."<<endl;}18doubleDiv(doublex,doubley){ doubletemp; temp=x,x=x+y,y=temp-y;if(y==0) throwy; returnx/y;}19程序在處理異常之后,繼續執行catch后面的if語句,直到結束。輸出結果如下:1.2963exceptofdevidingzero.Thereisanymistake.Exit...202.函數模板(FunctionTemplate)21模板的作用:一個函數或者類去處理不同的數據類型。使用模板可以使用戶為類或者函數聲明一種通用模式,使得類中的某些數據成員或者成員函數的參數、返回值取得任意類型。模板概述222.1函數模板的引入假如編寫一個函數,返回數的絕對值。對于int數據類型,此函數可寫為:

intabs(intn){ return(n<0)?–n:n; }對于long數據類型,此函數可寫為:

longabs(longn){ return(n<0)?–n:n; }對于float數據類型,此函數可寫為:

floatabs(floatn){ return(n<0)?–n:n; }23上面每個函數中,函數體都是一樣,只是參數類型和返回值類型不一樣。如果只把這個函數寫一遍,而讓其處理不同的數據類型,這正是函數模板所實現的。24函數模板就是一系列相似函數的模型。這些函數的代碼形式相同,只是所針對的參數和返回值的數據類型不同。25template<classT>Tfunc(Targ){…}一個函數模板intfunc(intarg){…}charfunc(chararg){…}floatfunc(floatarg){…}i1=func(i2);c1=func(c2);f1=func(f2);參數類型決定函數實例化262.2 函數模板的定義欲定義一函數為template函數,其格式如下:

template<classType>

//template定義部分Typefuncname(Type,Type…){}

//真正函數定義部分

關鍵字數據類型函數的參數行27見例:tempabs.cpp在程序中定義了可以處理多種數據類型的函數abs(): template<classT> Tabs(Tn) { return(n<0)?–n:n; }28函數模板定義的創新之處在于:函數所使用的參數,返回值用一個通用名字如Type(anyType,T…)替代了int,long,float

等特定的類型。29程序tempabs.cpp中,

cout<<“\nabs(”<<int<<“)=”<<abs(int1);當調用到函數abs(int1)時,編譯器才知道所用類型是int,因而用int代替abs模板中的所有T,這就是函數模板的實例化。

30函數模板并不是真正的函數,只是一種產生多種函數的模式或者框架,并不使程序代碼占用內存。312.3 多參數函數模板見例:tempfind.cpp此函數模板有三個參數,兩個是模板參數,一個是基本類型。此函數模板的作用是從數組中尋找特定的值,如果找到這個值,就返回所在位置,如果沒有找到,則返回-1。參數分別為指向數組的指針,要找的特定值和數組大小。32332.4 多種類型模板參數在模板函數中可以使用多種類型模板參數。其函數定義的格式如下:

template<classType1,classType2> Type1fun(Type1a,Type2b){…}Type1,Type2為不同數據類型,返回值可以為Type1,Type2或其他基本類型。34注意:在定義類型參數時,每一類型參數都必須跟著一個關鍵字class,以下的格式是錯誤的:

Template<classType1,Type2>

//error!!而對于函數參數表中,每一個已定義的類型參數都必須至少被使用一次。以下的格式是錯誤的:

template<classT1,classT2,classT3> T3fun(T1a,T1b,T2c){..}

//error!!35修改程序tempfind.cpp,定義數組大小的類型名為btype:

template<classatype,classbtype> btypefind(atype*arrary,atypevalue,btypesize) { for(btypej=0;j<size;j++) { if(arrary[j]==value) returnj; return-1; }這樣就可以使用int或者long類型作為數組大小。363. 類模板37模板的概念可以擴展到類。用一種類似函數模板的機制來解決類數據成員更改的問題——類模板。3.1 類模板的引入38例如:如下的stack類僅能存儲int類型

classStack{ private: intst[MAX];//arrayofints inttop;//indexnumberoftopofstack

public: Stack(); voidpush(intvar);//takesintasarg.

intpop();//returnsintvalue };39如果想在棧中存儲long類,則需要重新定義類:

classLongStack{ private: longst[MAX];//arrayoflongs inttop;//indexnumberoftopofstack

public: LongStack(); voidpush(longvar);//takeslongasarg.

longpop();//returnslongvalue };40如此一來,就需要為存儲的每種數據類型定義新的Stack類。如使用類模板就方便得多。類模板的格式如下:

template<classType> classStack { //dataandmemberfunctionsusingargumenttype };3.2 類模板的定義41見例:tempstack.cpp此例中,模板參數是Type,此參數出現在類定義中涉及到數組st類型的所有地方。與函數模板相同,類模板只有使用的時候才被具體化為某一種類型。42類模板和函數模板的不同之處在于:函數模板的使用是由編譯器自動決定的;而類模板定義對象時其真正類型必須由程序設計者自己指明。43例如:

Stack<float>s1;

此語句創建了對象s1,為s1的數據在內存中提供了空間;用float代替類定義中所有模板參數,同時也為成員函數提供內存空間。 如果創建其他類型的堆棧,如:

Stak<long>s2;

則為數據創建了不同的內存空間。44template<classT>classAclass{//statements….};源代碼中的一個類模板obj1storesfloatsobj2storeintsobj3storeintsobj4storescharsobj5storescharsAclass<float>obj1;Aclass<int>obj3;Aclass<int>obj2;Aclass<char>obj5;Aclass<char>obj4;內存中不同類的多個對象453. 命名空間46為什么需要命名空間?命名空間是C++中的一個不常用的概念。C++中采用的是單一的全局變量命名空間。在這單一的空間中,如果有兩個變量或函數的名字完全相同,就會出現沖突。47stringnamestringnamenamespacemynamespaceyour48命名空間定義名字空間的定義與一個類的定義非常相似:

namespaceMyLib{ //Declarations }在namespace定義的結尾,不必要跟一個分號。49namespace與class、structure、union和enum有著明顯的區別:

1)namespace只能在全局范疇定義,但它 們之間可以互相嵌套。

2)一個namespace可以在多個頭文件中。

3)不能像類那樣去創建一個命名空間的實例。50使用命名空間

1.域名 命名空間中的任何命名都可以用域名明確指定,就像引用一個類名一樣。51//兩個在不同命名空間中定義的名字相同的變量namespacemyown1{

stringuser_name="myown1";}namespacemyown2{

stringuser_name="myown2";}52intmain(){

cou

溫馨提示

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

評論

0/150

提交評論