一、關鍵點
異常:存在于運作時的反常行為,這些行為超出了函數正常功能的範圍。
典型的異常:失去資料庫連接配接、遇到意外輸入等。
異常處理機制:為程式中異常檢測和異常處理這兩部分的協作提供支援。
二、異常檢測
形式:throw 表達式;
解釋:上面的語句将引發(或抛出)一個異常,其中表達式的類型就是抛出的異常類型。
示例:throw runtime_error("自定義提示語"); //類型runtime_error就是一種異常類型
類型runtime_error:是标準庫異常類型中的一種,定義在stdexcept頭檔案中。我們必須初始化runtime_error的對象,方式是給它提供一個string對象或一個字元串字面值,這個字元串主要寫一些關于異常的輔助資訊。
————————————————2017-11-7更新補充————————————————
補充1:表達式不僅僅隻有一個異常類型(也就是抛出對象的類型),還包括抛出對象的内容,如throw runtime_error("除數不能為0"),其中标紅的地方就是抛出對象的内容。
補充2:throw語句執行完,就轉到對應的catch語句,而非繼續執行throw語句之後的語句。
補充3:異常對象,編譯器使用異常抛出表達式來對異常對象進行拷貝初始化(這是另一種抛出異常的形式:range_error r("errpr"); throw r;)
補充4:當異常處理完畢後,異常對象被銷毀(是以,如果異常抛出表達式是類類型的話,則相應的類必須含有一個可通路的析構函數)
——————————————————補充完畢———————————————————
三、異常處理
1. try語句塊
文法形式:
解釋:try語句塊中的program-statements組成程式的正常邏輯,像其他任何塊一樣,program-statements可以有包含聲明在内的任意C++語句。隻是在try語句塊内聲明的變量在塊外無法通路,即使是catch子句也無法通路。
2. catch子句
包括三部分:關鍵字catch、括号内一個(可能未命名的)對象的聲明(稱作異常聲明)、一個語句塊
多個catch子句:當選中了某個catch子句處理異常之後,執行與之對應的塊。
catch子句完成:程式跳轉到最後一個catch子句之後的那條語句繼續執行。
補充1:若找到一個比對的catch子句,則程式進入該子句并執行其中的代碼
補充2:當執行完這個catch子句後,找到與try塊關聯的最後一個catch子句之後的點,并從這裡繼續執行
補充3:異常聲明的類型決定了處理代碼所能捕獲的異常類型
補充4:進入一個catch語句後,通過異常對象初始化異常聲明中的參數
補充5:異常的類型和catch聲明的類型的比對規則:①允許從非常量向常量的類型轉換,即一個非常量對象的throw語句可以比對一個接受常量引用的catch語句;②允許從派生類向基類的類型轉換;③數組被轉換成指向數組(元素)類型的指針,函數被轉換成指向該函數類型的指針
補充6:捕獲所有異常的catch語句,形如catch(...),可以與任意類型的異常比對
四、尋找處理代碼的辛酸過程
1. try語句塊可能調用了包含另一個try語句塊的函數:使得程式在遇到抛出異常的代碼前,其執行路徑可能已經經過了多個try語句塊。
2. 尋找處理代碼的過程:當異常被抛出時,程式首先搜尋抛出該異常的函數,如果在目前函數沒找到比對的catch子句,就終止該函數,并在調用該函數的函數中繼續尋找。
3. 标準庫函數terminate:負責終止程式的執行過程,即程式最終都沒找到比對的catch子句,就執行該函數讓程式非正常退出。
4. 沒有定義try語句塊:此時發生異常,系統會調用terminate函數并終止目前程式的執行。
補充1:當抛出一個異常後,程式(暫停目前函數的執行過程)立即開始尋找與異常比對的catch子句
補充2:棧展開過程,沿着嵌套函數的調用鍊不斷查找,直到找到了與異常比對的catch子句為止(或者也可能一直沒找到比對的catch,則退出主函數後查找過程終止)
當throw出現在一個try語句塊内時,檢查與該try塊關聯的catch子句:
1)找到了比對的catch,就使用該catch處理異常
2)未找到比對的catch,
①該try語句嵌套在其他try塊中,則繼續檢查與外層try比對的catch子句
1° 還是找不到比對的catch,則退出目前的函數,在調用目前函數的外層函數中繼續尋找
補充3:若找到比對的catch并執行完該catch,程式跳轉到與try塊關聯的最後一個catch子句之後的那條語句繼續執行,這表明了可能會跳過許多函數、語句塊
五、異常類
1. 作用:報告标準庫函數遇到的問題,異常類也可以用在使用者編寫的程式中。
2. 定義異常類的4個頭檔案:
頭檔案名稱
說明
exception
定義了最通用的異常類exception,它隻報告異常的發生,不提供任何額外資訊
stdexcept
定義了幾種常用的異常類:exception、runtime_error、range_error等
new
定義了bad_alloc異常類型
type_info
定義了bad_cast異常類型
3. 頭檔案stdexcept中定義的異常類
異常類
錯誤類型
最常見的問題
runtime_error
隻有在運作時才能檢測出的問題
range_error
運作時錯誤:生成的結果超出了有意義的值域範圍
overflow_error
運作時錯誤:計算上溢
underflow_error
運作時錯誤:計算下溢
logic_error
程式邏輯錯誤
domain_error
邏輯錯誤:參數對應的結果值不存在
invalid_error
邏輯錯誤:無效參數
length_error
邏輯錯誤:試圖建立一個超出該類型最大長度的對象
out_of_range
邏輯錯誤:使用一個超出有效範圍的值
4. 異常類定義的幾種運算:建立或拷貝異常類型的對象、為異常類型的對象指派
5. 不能被提供初始值的對象:exception、bad_alloc、bad_cast對象,它們隻能以預設初始化的方式來初始化
6. 不能使用預設初始化的對象:除了上面的對象,其他對象在建立時必須提供初始值(string對象或字元串字面值),該初始值含有錯誤相關的資訊
7. 異常類的成員函數:隻有一個名為what的成員函數,該函數傳回值是一個const char *(字元串字面值),目的是提供關于異常的一些文本資訊。該字元串的内容與異常對象的類型有關,如果異常類型有一個字元串初始值,則what傳回該字元串。而對于無初始值的異常類型來說,what傳回的内容由編譯器決定。
六、示例
題目:編寫一個程式,從标準輸入讀取兩個整數,輸出第一個數除以第二個數的結果。要求:當第二個數是0時抛出異常,使用try語句塊去捕獲異常,catch子句應該為使用者輸出一條提示資訊,詢問是否輸入新數并重新執行try語句塊的内容。
代碼:

View Code
七、小結
一句話:try是檢測異常的,如果産生了異常,就throw(抛出)一個異常,然後被catch到,在catch塊中進行異常的處理。