您好,登錄后才能下訂單哦!
我們在進行異常分析的時候,如何判斷一個函數是否會拋出異常,以及拋出哪些異常呢?C++ 提供語法用于聲明函數所拋出的異常,異常聲明作為函數聲明的修飾符,寫在參數列表后面。如下
函數異常規格說明的意義是:a> 提供商函數調用者必須做好異常處理的準備;b> 提供函數的維護者不要拋出其他異常;c> 異常規格說明是函數接口的一部分。那么如果拋出的異常不在聲明列表中會發生什么?
下面我們還是以代碼為例來進行說明
#include <iostream> using namespace std; void func() throw(int) { cout << "func()" << endl; throw 'c'; } int main() { try { func(); } catch(int) { cout << "catch(int)" << endl; } catch(char) { cout << "catch(char)" << endl; } return 0; }
我們在 func 函數的后面只聲明有可能會拋出 int 類型的異常,實際我們拋出的是字符型異常,我們來看看在 main 函數中的 catch(char) 語句塊能捕獲到嗎?先來看看 g++ 編譯器下是怎樣的
運行的結果是沒有捕獲到 char 類型的異常,調用了 Aborted 函數。我們再用 BCC 編譯器試試
我們再來試試 vs2010 編譯器
我們看到在 vs2010 中捕獲到了拋出的異常。如果函數拋出的異常不在規格說明中,全局 unexpected() 被調用。默認的 unexpected() 函數會調用全局的 terminate() 函數,我們可以自定義函數替換默認的 unexpected() 函數實現。注意:不是所有的 C++ 編譯器都支持這個標準行為。
下來我們來說說 unexpected() 函數的替換:a> 自定義一個無返回值參數的函數,能夠再次拋出異常。當異常符合觸發函數的異常規格說明時,恢復程序執行。否則,調用全局 terminate() 函數結束程序;b> 調用 set_unexpected() 設置自定義的異常函數,參數類型為 void(*)(),返回值為默認的 unexpected() 函數入口地址。
我們來看看自定義 unexpected() 函數的代碼是怎么寫的
#include <iostream> #include <cstdlib> #include <exception> using namespace std; void my_unexpected() { cout << "void my_unexpected()" << endl; throw 1; } void func() throw(int) { cout << "func()" << endl; throw 'c'; } int main() { set_unexpected(my_unexpected); try { func(); } catch(int) { cout << "catch(int)" << endl; } catch(char) { cout << "catch(char)" << endl; } return 0; }
我們先來分析下,在 func 函數中聲明的異常是 int 類型的,但是拋出的 char 類型的。因此編譯器會調用我們設置的 my_unexpected() 函數,在 my_unexpected() 中又拋出了一個 int 類型的異常,因此便會被 main 函數中的 catch(int) 捕獲到,輸出 catch(int) 語句。我們來看看在 g++ 編譯器中是怎樣的
跟我們分析的是一致的,再來看看 vs2010 編譯器是怎樣的
它還是我行我素,沒一點變化。這便是我們之前說的不是所有的 C++ 編譯器都支持這個標準行為。通過對異常規格說明的學習,總結如下:1、C++ 中的函數可以聲明異常規格說明,異常規格說明可以看做接口的一部分;2、函數拋出的異常不在規格說明中,unexpected() 被調用;3、unexpected() 中能夠再次拋出異常:異常能夠匹配則恢復程序的執行,否則調用 terminate() 結束程序。
歡迎大家一起來學習 C++ 語言,可以加我QQ:243343083。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。