關(guān)于C++中的異常處理使用方法與技巧_第1頁
關(guān)于C++中的異常處理使用方法與技巧_第2頁
免費(fèi)預(yù)覽已結(jié)束,剩余1頁可下載查看

下載本文檔

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

文檔簡介

1、1關(guān)于異常處理1.1 為什么要拋出異常拋出異常的好處一是可以不干擾正常的返回值,另一個(gè)是調(diào)用者必須處理異常,而不像以前c語言返回一個(gè)整數(shù)型的錯(cuò)誤碼,調(diào)用者往往將它忽略了。C+的異常處理確保當(dāng)程序的執(zhí)行流程離開一個(gè)作用域的時(shí)候?qū)τ趯儆谶@個(gè)作用域的所有由構(gòu)造函數(shù)建立起來的對(duì)象,它們的析構(gòu)函數(shù)一定會(huì)被調(diào)用。1.2 捕獲所有異常有時(shí)候,程序員可能希望創(chuàng)建一個(gè)異常處理器,使其能夠捕獲所有類型的異常。用省略號(hào)代替異常處理器的參數(shù)列表就可以實(shí)現(xiàn)這一點(diǎn):catch(.,.)coutanexceptionwasthrownHendl;/Deallocateyourresourcehere,andthenreth

2、rowthrow:由于省略號(hào)異常處理器能夠捕獲任何類型的異常,所以最好將它放在異常處理器列表的最后,從而避免架空它后面的異常處理器。省略號(hào)異常處理器不允許接受任何參數(shù),所以無法得到任何有關(guān)異常的信息,也無法知道異常的類型。它是一個(gè)“全能捕獲者”。這種catch子句經(jīng)常用于清理資源并重新拋出所捕獲的異常。1.3 重新拋出異常當(dāng)需要釋放某些資源時(shí),例如網(wǎng)絡(luò)連接或位于堆上的內(nèi)存需要釋放時(shí),通常希望重新拋出一個(gè)異常。(詳見本章后面的“資源管理”一節(jié)。)如果發(fā)生了異常,讀者不必關(guān)心到底是什么錯(cuò)誤導(dǎo)致了異常的發(fā)生只需要關(guān)閉以前打開的一個(gè)連接。此后,讀者希望在某些更接近用戶的語境(也就是說,在調(diào)用鏈中的更高

3、層次)中對(duì)異常進(jìn)行處理。在這種情況下,省略號(hào)異常處理器正符合這種的要求。這種處理方法,可以捕獲所有異常,清理相關(guān)資源,然后重新拋出該異常,以使得其他地方的異常處理器能夠處理該異常。在一個(gè)異常處理器內(nèi)部,使用不帶參數(shù)的throw語句可以重新拋出異常:catch(.,-)coutanexceptionwasthrown1endl;/Deallocateyourresourcehere,andthenrethrowthrow:與同一個(gè)try塊相關(guān)的隨后的catch子句仍然會(huì)被忽略throw子句把這個(gè)異常傳遞給位于更高一層語境中的異常處理器。另外,這個(gè)異常對(duì)象的所有信息都會(huì)保留,所以位于更高層語境中的

4、捕獲特定類型異常的異常處理器能夠獲取這個(gè)對(duì)象包含的所有信息。1.4 構(gòu)造函數(shù)中的異常C+規(guī)定構(gòu)造函數(shù)拋出異常之后,對(duì)象將不被創(chuàng)建,析構(gòu)函數(shù)也不會(huì)被執(zhí)行,但已經(jīng)創(chuàng)建成功的部分(比如一個(gè)類成員變量)會(huì)被部分逆序析構(gòu),不會(huì)產(chǎn)生內(nèi)存泄漏。但有些資源需要在拋出異常前自己清理掉,比如打開成功的一個(gè)文件,最好關(guān)閉掉再拋出異常(雖然系統(tǒng)也會(huì)把這個(gè)資源回收),因?yàn)閽伋霎惓V笪鰳?gòu)函數(shù)不會(huì)被執(zhí)行了。(1)C+中通知對(duì)象構(gòu)造失敗的唯一方法那就是在構(gòu)造函數(shù)中拋出異常;(這句話并不是說我們只有這個(gè)方法才能讓上層知道構(gòu)造函數(shù)失敗,雖然構(gòu)造函數(shù)沒有返回值,我們完全可以在構(gòu)造函數(shù)中傳入一個(gè)引用值,然后在里面設(shè)置狀態(tài),運(yùn)行完構(gòu)

5、造函數(shù)之后任然可以知道是否失敗,但這種情況下面對(duì)象其實(shí)還是被構(gòu)造出來的,只是里面有資源分配失敗而已,并且析構(gòu)函數(shù)還是會(huì)執(zhí)行。這和我們構(gòu)造失敗不生成對(duì)象的初衷不符。)(2)構(gòu)造函數(shù)中拋出異常將導(dǎo)致對(duì)象的析構(gòu)函數(shù)不被執(zhí)行;(但已經(jīng)生產(chǎn)的部分成員變量還是會(huì)被逆向析構(gòu)的)(3)當(dāng)對(duì)象發(fā)生部分構(gòu)造時(shí),已經(jīng)構(gòu)造完畢的子對(duì)象將會(huì)逆序地被析構(gòu);對(duì)于構(gòu)造函數(shù)可能失敗的做法一般有兩種1.在構(gòu)造函數(shù)中拋出異常,本對(duì)象構(gòu)造未完成,它的析構(gòu)函數(shù)不會(huì)被調(diào)用。當(dāng)然,我們有義務(wù)釋放已經(jīng)分配到的資源。簡單,最常見。2.把資源的初始化工作放在另一個(gè)單獨(dú)函數(shù)中,比如boolinit(.),由對(duì)象創(chuàng)建者(比如工廠方法)先調(diào)用構(gòu)造函數(shù)

6、,再調(diào)用init方法。ATL中常見。1.5 析構(gòu)函數(shù)中的異常C+標(biāo)準(zhǔn)指明析構(gòu)函數(shù)不能、也不應(yīng)該拋出異常,在析構(gòu)函數(shù)中拋出錯(cuò)誤,通常被認(rèn)為象征著拙劣的設(shè)計(jì)或糟糕的編碼。這是因?yàn)椋何鰳?gòu)函數(shù)如果拋出異常,將會(huì)導(dǎo)致調(diào)用標(biāo)準(zhǔn)庫terminate函數(shù),而terminate函數(shù)將調(diào)用abort函數(shù),導(dǎo)致程序的非正常退出。所以析構(gòu)函數(shù)應(yīng)該從不拋出異常。析構(gòu)函數(shù)不能拋出異常的理由:1)如果析構(gòu)函數(shù)拋出異常,則異常點(diǎn)之后的程序不會(huì)執(zhí)行,如果析構(gòu)函數(shù)在異常點(diǎn)之后執(zhí)行了某些必要的動(dòng)作比如釋放某些資源,則這些動(dòng)作不會(huì)執(zhí)行,會(huì)造成資源泄漏。2)通常異常發(fā)生時(shí),C+的機(jī)制會(huì)調(diào)用已經(jīng)構(gòu)造對(duì)象的析構(gòu)函數(shù)來釋放資源,此時(shí)若析構(gòu)函

7、數(shù)本身也拋出異常,則前一個(gè)異常尚未處理,又有新的異常,會(huì)造成程序崩潰。那么當(dāng)無法保證在析構(gòu)函數(shù)中不發(fā)生異常時(shí),該怎么辦?其實(shí)還是有很好辦法來解決的。那就是把異常完全封裝在析構(gòu)函數(shù)內(nèi)部,決不讓異常拋出函數(shù)之外。這是一種非常簡單,也非常有效的方法。ClassName()trydo_something();catch(.)這里可以什么都不做,只是保證catch塊的程序拋出的異常不會(huì)被扔出析構(gòu)函數(shù)之外。1.6 不會(huì)拋出的異常C+為什么抓不到除0錯(cuò)的“異?!??說起來,和原生數(shù)組訪問越界為什么不是異常并無兩樣,主要還是為了“效率/性能”。對(duì)于大多數(shù)時(shí)候的除法操作,我們會(huì)讓它出現(xiàn)除數(shù)為0的可能性很小,當(dāng)你認(rèn)

8、為有這種可能,就自己檢查吧,然后自己定義一個(gè)除0錯(cuò)的異常。1.7 自定義異常C+可以返回任意類型異常,包括標(biāo)準(zhǔn)異常類、基本數(shù)據(jù)類型、用戶自定義的任意類(不一定要從excption繼承。但是,如果要使用統(tǒng)一的基類捕捉異常,就必須從excption繼承,且繼承時(shí)要注意以下問題:異常信息應(yīng)該通過構(gòu)造函數(shù)傳入,最好通過what()函數(shù)來返回。示例如下:classCtpException:publicQExceptionpublic:CtpException(QString&className,QString&funcName,QString&locationMark&,QStringerrMsg)ms

9、g.append(className);msg.append(.);msg.append(funcName);msg.append(.);msg.append(locationMark);msgappend(,發(fā)生異常:);msg.append(errMsg);constchar*what()constthrow()returnmsg.constData();private:QByteArraymsg;1.8 通過引用捕獲異常不要使用new來拋出異常,不要使用指針或者傳值的方式捕獲異常。應(yīng)該直接使用throwCtpException拋出異常,表示將異常放到棧中,就可以自動(dòng)釋放。應(yīng)該使用std:

10、exception&來捕獲異常,一定要寫&,這樣才能防止異??截?,并且可以做到使用父類對(duì)象捕獲子類的異常信息。tryQStringclsName=MainWindow;QStringfunName=on_pushButton_3_clicked();QStringerrMsg=自定義錯(cuò)誤;QStringlocationMark=location-1;throwCtpException(clsName,funName,errMsg,locationMark);catch(std:exception&e)qDebug()vvexception:vve.what();Catch,”1.9 如何獲得異

11、常發(fā)生位置當(dāng)程序發(fā)生異常時(shí),我們非常需要知道哪里發(fā)生了異常。在java等語言中,可通過異常堆棧獲得異常發(fā)生位置,但是在C+中,沒有異常堆棧。因此,可通過在每個(gè)函數(shù)中進(jìn)行錯(cuò)誤捕捉來獲得異常發(fā)生位置。示例如下:voidDBAccess:execBatchNonQuery(QSqlQuery&query,constQString&sqlStr,constQList&ColumnValueSet)tryquery.prepare(sqlStr);for(inti=0;iColumnValueSet.length();i+)query.addBindValue(ColumnValueSeti);boolresult=query.execBatch();if(!result)QStringerrMsg=QSt

溫馨提示

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

評(píng)論

0/150

提交評(píng)論