【C++】C++異常處理

一、什麼是異常?
異常就是程序在運行過程中,由於使用環境的變化及用戶的錯誤操作而產生的錯誤。
二、傳統錯誤處理辦法:
1.終止程序(除數爲0)
2.返回一個表示錯誤的值,附加錯誤碼(GetLastError())
3.返回一個合法值,讓程序處於某種非法的狀態(坑爹的atoi())
4.調用一個預先準備好在出現”錯誤”的情況下用的函數(回調函數)。
5.暴力解決方式:abort()或者exit()
6.使用goto語句
三、異常處理語句塊
1.try語句塊
用來框定異常。在程序中,需要先框定可能產生異常的語句塊。若不框定就等於沒有發現異常的存在。

try
{
內嵌throw語句的語句;
}

try語句塊一般包含一個以上的throw語句塊,如果沒有包含任何throw語句,程序會根據運行情況,拋出默認的錯誤。
try語句塊後面必須包含最少一個catch語句塊。如果try語句後面帶有多個catch語句塊,則需要和throw拋出的數據類型匹配,匹配成功後進行相應的catch語句塊的異常處理語句。
2.throw語句塊
(1)帶表達式的形式

throw type exception;

type表示已經聲明的數據類型,如float、long以及結構類型。exception表示變量名,可添加也可不添加。
(2)不帶表達式的形式:

throw;

throw拋出的不僅是表達式,也可以是具體的值,其中類型最爲重要。拋出的數據有catch語句接受,接受原則是先按照類型匹配,如果有多個catch語句類型都匹配,則按照就近原則接受。既有數值也有該數值對應的類型時,類型是第一重要的。其次纔是數值。
3.catch語句塊
用來處理try塊中拋出的異常

catch(type[exception])//匹配throw拋出的exception語句塊;
{
   //匹配成功後,處理異常語句放在這裏
}
catch(...)//匹配throw拋出的任意類型語句塊
{
   //語句
}

catch後面圓括號包含的參數只能有一個,參數入口的類型名稱是不可缺少的,但是形參exception則是可有可無。

異常的流程是:
首先檢測觸發throw語句所在的函數,明確throw語句所屬try塊,如果這一檢測成功,就按照throw語句拋出的數據類型,在try塊管轄的catch塊根據其先後出現的次序比較,如果查詢到剛好捕獲相應類型的catch塊時,就運行相應catch塊語句。

使用try-catch處理異常的格式爲:

try
{
   Throw param1;
   Throw type2 [param2];
}
catch(type1 )
{
   語句1;
}
catch(type2 [param2])
{
   語句塊n;
}
catch(...)  //匹配throw拋出的任意類型的語句塊;
{
   ...
}

四、異常的拋出和捕獲
1. 異常是通過拋出對象而引發的,該對象的類型決定了應該激活哪個處理代碼。
2. 被選中的處理代碼是調用鏈中與該對象類型匹配且離拋出異常位置最近的那一個。
3. 拋出異常後會釋放局部存儲對象,所以被拋出的對象也就還給系統了,throw表達式會初始化一個拋出特殊的異常對象副本(匿名對象),異常對象由編譯管理,異常對象在傳給對應的catch處理之後撤銷。
五、棧展開
拋出異常的時候,將暫停當前函數的執行,開始查找對應的匹配catch子句。
首先檢查throw本身是否在try塊內部,如果是再查找匹配的catch語句。
如果有匹配的,則處理。沒有則退出當前函數棧,繼續在調用函數的棧中進行查找。
不斷重複上述過程。若到達main函數的棧,依舊沒有匹配的,則終止程序。
上述這個沿着調用鏈查找匹配的catch子句的過程稱爲棧展開。
找到匹配的catch子句並處理以後,會繼續沿着catch子句後面繼續執行。
六、異常捕獲的匹配規則
異常對象的類型與catch說明符的類型必須完全匹配。只有以下幾種情況例外
1. 允許從非const對象到const的轉換。
2. 允許從派生類型到基類類型的轉換。
3. 將數組轉換爲指向數組類型的指針,將函數轉換爲指向函數類型的指針。
七、異常的重新拋出
有可能單個的catch不能完全處理一個異常,在進行一些校正處理以後,希望再交給更外層的調用鏈函數來處理,catch則可以通過重新拋出將異常傳遞給更上層的函數進行處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章