C++異常處理
一個問題是程序在執行期間產生了一個例外。 C++異常是一個特殊的情況在程序運行時,比如試圖除以零而引致的響應結果。
異常提供一種方法來從一個程序到另一個程序的一個部分轉移控製。 C++異常處理建立在三個關鍵字: try, catch,和 throw。
-
throw: 程序拋出一個異常在當問題出現時。這是通過使用一個throw關鍵字。
-
catch: 程序捕獲異常,並在要處理的問題,程序異常處理程序地方。關鍵字表示異常的醒目。
-
try: try塊標識代碼塊的哪些特定的異常將被激活。它的後麵是一個或多個catch塊。
假設一個塊將拋出一個異常,方法使用try和catch關鍵字的組合捕獲異常。try/ catch塊周圍放置可能產生異常的代碼。try / catch塊中的代碼被稱為保護代碼,使用try/ catch語句的語法如下所示:
try { // protected code }catch( ExceptionName e1 ) { // catch block }catch( ExceptionName e2 ) { // catch block }catch( ExceptionName eN ) { // catch block }
可以列出多個catch語句捕獲不同類型的異常的情況,try塊中引發不同的情況而可能不止一個例外。
拋出異常:
異常可以在任何地方使用throw語句代碼塊拋出。throw語句操作確定一個類型的異常,可以是任意表達式和表達式的結果的類型決定拋出的異常的類型。
以下是當通過除以零發生拋出異常的一個例子:
double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); }
捕獲異常:
以下的try catch塊捕獲任何異常。可以指定想要捕捉什麼樣的類型異常,出現在以下關鍵字catch括號中的例外聲明確定。
try { // protected code }catch( ExceptionName e ) { // code to handle ExceptionName exception }
上麵的代碼會捕獲ExceptionName類型的異常。如果想指定catch塊應該處理任何類型拋出異常在try塊,必須把省略號,...,封閉異常聲明如下括號:
try { // protected code }catch(...) { // code to handle any exception }
下麵是一個例子,它除以零拋出一個異常,它的catch塊捕獲。
#include <iostream> using namespace std; double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); } int main () { int x = 50; int y = 0; double z = 0; try { z = division(x, y); cout << z << endl; }catch (const char* msg) { cerr << msg << endl; } return 0; }
因為我們是拋出一個異常類型為const char*,因此,要捕獲這種異常,我們必須使用為const char*在catch塊中。編譯並運行上麵的代碼,這會產生以下結果:
Division by zero condition!
C++標準例外:
C++提供的<exception>,可以在程序中使用定義的標準異常列表。這些被組織在以下所示的父子類層次結構:
Exception | 描述 |
---|---|
std::exception | 一個例外,所有標準C++異常的父類 |
std::bad_alloc | 這可以通過new 拋出 |
std::bad_cast | 這可以通過 dynamic_cast 拋出 |
std::bad_exception | 這是非常有用的設備用來處理在C++程序意外異常 |
std::bad_typeid | 這可以通過 typeid. 拋出 |
std::logic_error | 理論上可以通過讀取代碼來檢測異常 |
std::domain_error | 這是拋出一個異常,當一個數學無效域使用 |
std::invalid_argument | 這是由於無效的參數異常 |
std::length_error | 創建太長的 std::string 時,這將被拋出 |
std::out_of_range | 這可以通過在一個方法拋出,例如 std::vector 和 std::bitset<>::operator[](). |
std::runtime_error | 理論上無法通過讀取碼來檢測的異常 |
std::overflow_error | 如果一個數學溢出,就會發生此異常 |
std::range_error | 當嘗試存儲值超出範圍,將發生此異常 |
std::underflow_error | 如果一個數學溢出,就會發生此異常 |
定義新的異常:
可以通過繼承並覆蓋異常類的功能定義自己的異常。以下為例子,它說明了如何使用std::異常類來實現自己的標準方式的例外:
#include <iostream> #include <exception> using namespace std; struct MyException : public exception { const char * what () const throw () { return "C++ Exception"; } }; int main() { try { throw MyException(); } catch(MyException& e) { std::cout << "MyException caught" << std::endl; std::cout << e.what() << std::endl; } catch(std::exception& e) { //Other errors } }
這將產生以下結果:
MyException caught C++ Exception
在這裡,what()是異常類提供一個公共方法,它已被所有子異常類覆蓋。這將返回一個異常的原因。