走進C 程式世界 異常處理

2021-09-08 22:44:43 字數 3864 閱讀 3415

一、 概述

c++自身有著很強的糾錯能力,發展到現在,已經建立了比較完好的異常處理機制。

c++的異常情況無非兩種,一種是語法錯誤。即程式**現了錯誤的語句,函式。結構和類,致使編譯程式無法進行。還有一種是執行時發生的錯誤。一般與演算法有關。

關於語法錯誤,不必多說,寫**時心細一點就能夠解決。c++編譯器的報錯機制能夠讓我們輕鬆地解決這些錯誤。

第二種是執行時的錯誤,常見的有檔案開啟失敗、陣列下標溢位、系統記憶體不足等等。而一旦出現這些問題。引發演算法失效、程式執行時無故停止等故障也是常有的。

這就要求我們在設計軟體演算法時要全面。比方針對檔案開啟失敗的情況。保護的方法有非常多種。最簡單的就是使用「return」命令,告訴上層呼叫者函式執行失敗;第二種處理策略就是利用c++的異常機制,丟擲異常。

二、c++異常處理機制

c++異常處理機制是乙個用來有效地處理執行錯誤的很強大且靈活的工具,它提供了很多其它的彈性、安全性和穩固性,克服了傳統方法所帶來的問題.

異常的丟擲和處理主要使用了下面三個keyword: try、 throw 、 catch 。

丟擲異常即檢測是否產生異常,在c++中。其採用throw語句來實現,假設檢測到產生異常。則丟擲異常。

該語句的格式為:

throw 表示式;

假設在try語句塊的程式段中(包含在當中呼叫的函式)發現了異常,且拋棄了該異常,則這個異常就能夠被try語句塊後的某個catch語句所捕獲並處理。捕獲和處理的條件是被拋棄的異常的型別與catch語句的異常型別相匹配。因為c++使用資料型別來區分不同的異常,因此在推斷異常時。throw語句中的表示式的值就沒有實際意義,而表示式的型別就特別重要。

try-catch語句形式例如以下 :

try

catch

(型別名 [形參名]) 

// 捕獲特定型別的異常

catch

(型別名 [形參名]) 

// 捕獲特定型別的異常

catch

(...)    

// 三個點則表示捕獲全部型別的異常

【範例1】處理除數為0的異常。該範例將上述除數為0的異常能夠用try/catch語句來捕獲異常。並使用throw語句來丟擲異常,從而實現異常處理。實現**如**清單1-1所看到的。

// **清單1-1

#include//包括標頭檔案 

#include

double

fuc(

double

x, double

y) //定義函式

return

x/y;     

//否則返回兩個數的商

}  void

main()  

catch

(double

)             

//捕獲並處理異常

} 【範例2】自己定義異常型別 (在本文開始的**中已經給出示範)

三、異常的介面宣告

為了加強程式的可讀性,使函式的使用者可以方便地知道所使用的函式會丟擲哪些異常,可以在函式的宣告中列出這個函式可能丟擲的全部異常型別。比如:

void fun() 

throw( a,b,c,d);

這表明函式fun()可能而且僅僅可能丟擲型別(a,b,c,d)及其子型別的異常。

假設在函式的宣告中沒有包含異常的介面宣告,則此函式能夠丟擲不論什麼型別的異常,比如:

void fun();

乙個不會丟擲不論什麼型別異常的函式能夠進行例如以下形式的宣告:

void fun() thow();

五、異常處理中須要注意的問題

1. 假設丟擲的異常一直沒有函式捕獲(catch),則會一直上傳到c++執行系統那裡。導致整個程式的終止

2. 一般在異常丟擲後資源能夠正常被釋放。但注意假設在類的建構函式中丟擲異常。系統是不會呼叫它的析構函式的。處理方法是:假設在建構函式中要丟擲異常,則在丟擲前要記得刪除申請的資源。

3. 異常處理只通過型別而不是通過值來匹配的,所以catch塊的引數能夠沒有引數名稱,只須要引數型別。

4. 函式原型中的異常說明要與實現中的異常說明一致,否則easy引起異常衝突。

5. 應該在throw語句後寫上異常物件時,throw先通過copy建構函式構造乙個新物件,再把該新物件傳遞給 catch. 

那麼當異常丟擲後新物件怎樣釋放?

異常處理機制保證:異常丟擲的新物件並不是建立在函式棧上,而是建立在專用的異常棧上,因此它才幹夠跨接多個函式而傳遞到上層,否則在棧清空的過程中就會被銷毀。全部從try到throw語句之間構造起來的物件的析構函式將被自己主動呼叫。但假設一直上溯到main函式後還沒有找到匹配的catch塊,那麼系統呼叫terminate()終止整個程式,這樣的情況下不能保證全部區域性物件會被正確地銷毀。

6. catch塊的引數推薦採用位址傳遞而不是值傳遞。不僅能夠提高效率,還能夠利用物件的多型性。

另外。派生類的異常撲獲要放到父類異常撲獲的前面,否則,派生類的異常無法被撲獲。

7. 編寫異常說明時,要確保派生類成員函式的異常說明和基類成員函式的異常說明一致,即派生類改寫的虛函式的異常說明至少要和相應的基類虛函式的異常說明同樣。甚至更加嚴格,更特殊。

#include "stdafx.h"  

#include#include#include // 記憶體洩露檢測機制

#define _crtdbg_map_alloc

#ifdef _debug

#define new new(_normal_block, __file__, __line__)

#endif

// 自己定義異常類

class myexcepction

// 拷貝建構函式

myexcepction( myexcepction& myexp)

~myexcepction()

// 獲取錯誤碼

int geterrorid()

private:

// 錯誤碼

int m_errorid;

};

int main(int argc, char* ar**)

else if ( throwerrorcode == 119 )

else if ( throwerrorcode == 120 )

else

} catch( myexcepction* pmyexcepction)

catch ( myexcepction myexcepction)

catch(...)

// 暫停

int temp;

std::cin >> temp;

return 0;

/*file : exception.cpp

*auth : sjin

*date : 20140515

*mail : [email protected]

*/#include #include using namespace std;

class myexcception:public exception

};/*假設丟擲異常,沒有接收。程式將終止*/

void exception_1()throw(double,int,const char *,myexcception)

{ int i;

cout << "輸入1-3整數" <> i;

if(i == 1)throw myexcception();

if(i == 2)throw "hello";

if(i== 3)throw 123;

cout << "**********end *****====" <

異常處理程式(Exception handler)

當然,丟擲的異常必須在某處得到處理。這個 地點 就是 異常處理程式 exception handler 針對每個要捕獲的異常,你得準備相應的處理程式。異常處理程式緊跟在 try 區塊之後,以關鍵字 catch 表示 try catch type1 id1 catch type2 id2 catch ...

程式的異常處理

二 什麼時候處理異常 僅當以下一種或多種情況時,我們的 才需要抓住異常 1.記錄異常 logging 將異常記錄到日誌中,便於support人員查詢錯誤原因。2.為這個異常新增相關資訊 wrap exception 加發生異常的環境資訊記錄,並產生新異常,交給呼叫本方法的 負責處理。3.執行清理工作...

帶您走進松本行弘的程式世界

本書的目的不是深入講解哪種特定的技術,也沒有全面討論我所開發的程式語言ruby,而是從全域性角度考察了與程式設計相關的各種技術。讀者千萬不要 以為拿著這本書,就可以按圖索驥地解決實際問題了。實際上,最好把它看成是一幅粗略勾勒出了程式設計世界諸要素之間關係的 世界地圖 每種技術 思想都有其特定的目的 ...