程式中的錯誤分為編譯時的錯誤和執行時的錯誤。編譯時的錯誤主要是語法錯誤,比如:句尾沒有加分號,括號不匹配,關鍵字錯誤等,這類錯誤比較容易修改,因為編譯系統會指出錯誤在第幾行,什麼錯誤。而執行時的錯誤則不容易修改,因為其中的錯誤是不可預料的,或者可以預料但無法避免的,比如記憶體空間不夠,或者在呼叫函式時,出現陣列越界等錯誤。如果對於這些錯誤沒有採取有效的防範措施,那麼往往會得不到正確的執行結果,程式不正常終止或嚴重的會出現宕機現象。我們把程式執行時的錯誤統稱為異常,對異常處理稱為異常處理。c++中所提供的異常處理機制結構清晰,在一定程度上可以保證程式的健壯性。
c++中處理異常的過程是這樣的:在執行程式發生異常,可以不在本函式中處理,而是丟擲乙個錯誤資訊,把它傳遞給上一級的函式來解決,上一級解決不了,再傳給其上一級,由其上一級處理。如此逐級上傳,直到最高一級還無法處理的話,執行系統會自動呼叫系統函式terminate,由它呼叫abort終止程式。這樣的異常處理方法使得異常引發和處理機制分離,而不在同乙個函式中處理。這使得底層函式只需要解決實際的任務,而不必過多考慮對異常的處理,而把異常處理的任務交給上一層函式去處理。
c++的異常處理機制有3部分組成:try(檢查),throw(丟擲),catch(捕獲)。把需要檢查的語句放在try模組中,檢查語句發生錯誤,throw丟擲異常,發出錯誤資訊,由catch來捕獲異常資訊,並加以處理。一般throw丟擲的異常要和catch所捕獲的異常型別所匹配。異常處理的一般格式為:
try被檢查語句
throw 異常
catch(異常型別1)
進行異常處理的語句1
catch(異常型別2)
進行異常處理的語句2
下面我們用示例演示一下異常處理:
#include "stdafx.h"
#include template t div(t x,t y)
int main()
模組根本沒有被執行。如果,我們把y的值改為1,則結果就變成為:
如果在執行try語句模組時,沒有發生異常,則catch語句塊不起作用,流程轉到其後的語句繼續執行。從上述兩個結果中可知第一次throw丟擲的int型別所以找到處理該型別的catch,而第二次是丟擲double型別所找到的是處理double型別的catch。
下面對異常處理補充幾點:(1)try和catch塊中必須要用花括號括起來,即使花括號內只有乙個語句也不能省略花括號;(2)try和catch必須成對出現,乙個try_catch結果中只能有乙個try塊,但可以有多個catch塊,以便與不同的異常資訊匹配;(3)如果在catch塊中沒有指定異常資訊的型別,而用刪節號"...",則表示它可以捕獲任何型別的異常資訊;(4)如果throw不包括任何表示式,表示它把當前正在處理的異常資訊再次丟擲,傳給其上一層的catch來處理;(5)c++中一旦丟擲乙個異常,如果程式沒有任何的捕獲,那麼系統將會自動呼叫乙個系統函式terminate,由它呼叫abort終止程式;
最後還是一樣,我將用乙個示例來總結一下今天所講的內容(開發工具:vs2010):
view code
#include "stdafx.h"
#include template t div(t x,t y)
int main()
// 拷貝建構函式
myexcepction( myexcepction& myexp)
~myexcepction()
// 獲取錯誤碼
int geterrorid()
private:
// 錯誤碼
int m_errorid;
}; int main(int argc, char* argv)
else if ( throwerrorcode == 119 )
else if ( throwerrorcode == 120 )
else }
catch( myexcepction* pmyexcepction)
catch ( myexcepction myexcepction)
catch(...)
// 暫停
int temp;
std::cin >> temp;
return 0;
}
異常的介面宣告:
為了加強程式的可讀性,使函式的使用者能夠方便地知道所使用的函式會丟擲哪些異常,可以在函式的宣告中列出這個函式可能丟擲的所有異常型別,例如:
void fun() throw( a,b,c,d);
這表明函式fun()可能並且只可能丟擲型別(a,b,c,d)及其子型別的異常。
如果在函式的宣告中沒有包括異常的介面宣告,則此函式可以丟擲任何型別的異常,例如:
void fun();
乙個不會丟擲任何型別異常的函式可以進行如下形式的宣告:
void fun() thow();
異常處理中需要注意的問題:
1. 如果丟擲的異常一直沒有函式捕獲(catch),則會一直上傳到c++執行系統那裡,導致整個程式的終止
2. 一般在異常丟擲後資源可以正常被釋放,但注意如果在類的建構函式中丟擲異常,系統是不會呼叫它的析構函式的,處理方法是:如果在建構函式中要丟擲異常,則在丟擲前要記得刪除申請的資源。
3. 異常處理僅僅通過型別而不是通過值來匹配的,所以catch塊的引數可以沒有引數名稱,只需要引數型別。
4. 函式原型中的異常說明要與實現中的異常說明一致,否則容易引起異常衝突。
5. 應該在throw語句後寫上異常物件時,throw先通過copy建構函式構造乙個新物件,再把該新物件傳遞給 catch.
那麼當異常丟擲後新物件如何釋放?
異常處理機制保證:異常丟擲的新物件並非建立在函式棧上,而是建立在專用的異常棧上,因此它才可以跨接多個函式而傳遞到上層,否則在棧清空的過程中就會被銷毀。所有從try到throw語句之間構造起來的物件的析構函式將被自動呼叫。但如果一直上溯到main函式後還沒有找到匹配的catch塊,那麼系統呼叫terminate()終止整個程式,這種情況下不能保證所有區域性物件會被正確地銷毀。
6. catch塊的引數推薦採用位址傳遞而不是值傳遞,不僅可以提高效率,還可以利用物件的多型性。另外,派生類的異常撲獲要放到父類異常撲獲的前面,否則,派生類的異常無法被撲獲。
7. 編寫異常說明時,要確保派生類成員函式的異常說明和基類成員函式的異常說明一致,即派生類改寫的虛函式的異常說明至少要和對應的基類虛函式的異常說明相同,甚至更加嚴格,更特殊。
**:**:
C 之異常處理
基本理念 問題的檢測和問題的解決分離,程式的問題檢測部分可以不用了解如何處理問題 異常處理是一同通訊機制,程式的不同部分就出現了什麼錯誤進行通訊 異常是通過丟擲 throw 物件而引發 raise 的,該物件的型別決定了應該啟用哪個處理 被選中的處理 是呼叫鏈中與該物件型別匹配且離丟擲異常位置最為接...
C 之異常處理
1 用try.catch.捕獲異常 注 convert是乙個類,代表型別轉換的類。toint32 是convert的乙個方法,這個方法的功能就是把指定的內容轉換成整數型別 namespace 異常 catch exception ex 出錯則執行 console.readkey 執行結果 2 異常前...
C 之異常處理
try catch exceptionname e1 catch exceptionname e2 catch exceptionname en finally 異常類 描述 system.io.ioexception 處理 i o 錯誤。system.indexoutofrangeexceptio...