C++異常處理



異常是在程式執行期間出現的錯誤。C++異常是對程式執行期間出現的異常情況的響應,例如嘗試除以零。

異常提供了一種將控制從程式的一個部分轉移到另一個部分的方法。C++異常處理建立在三個關鍵字之上:try、catchthrow

  • throw − 當出現問題時,程式會丟擲異常。這是使用throw關鍵字完成的。

  • catch − 程式在程式中要處理問題的地方使用異常處理程式捕獲異常。catch關鍵字表示捕獲異常。

  • trytry塊標識將為其啟用特定異常的程式碼塊。它後面跟著一個或多個catch塊。

假設一個塊將引發異常,則方法使用trycatch關鍵字的組合來捕獲異常。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*,所以在捕獲此異常時,我們必須在catch塊中使用const char*。如果我們編譯並執行上面的程式碼,則會產生以下結果:

Division by zero condition!

C++標準異常

C++提供在<exception>中定義的標準異常列表,我們可以在程式中使用。這些異常按如下所示的父子類層次結構排列:

C++ Exceptions Hierarchy

以下是上述層次結構中每個異常的簡短說明:

序號 異常及描述
1

std::exception

一個異常,也是所有標準C++異常的父類。

2

std::bad_alloc

這可能由new丟擲。

3

std::bad_cast

這可能由dynamic_cast丟擲。

4

std::bad_exception

這是一個有用的工具,用於處理C++程式中的意外異常。

5

std::bad_typeid

這可能由typeid丟擲。

6

std::logic_error

理論上可以透過閱讀程式碼檢測到的異常。

7

std::domain_error

當使用數學上無效的域時丟擲的異常。

8

std::invalid_argument

由於無效引數而丟擲。

9

std::length_error

當建立太大的std::string時丟擲。

10

std::out_of_range

例如,這可能由'at'方法(例如std::vector和std::bitset<>::operator[]())丟擲。

11

std::runtime_error

理論上無法透過閱讀程式碼檢測到的異常。

12

std::overflow_error

如果發生數學溢位,則會丟擲此異常。

13

std::range_error

當您嘗試儲存超出範圍的值時發生。

14

std::underflow_error

如果發生數學下溢,則會丟擲此異常。

定義新的異常

您可以透過繼承和重寫exception類的功能來定義自己的異常。

示例

以下示例顯示瞭如何使用std::exception類以標準方式實現您自己的異常:

#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()是exception類提供的公共方法,所有子異常類都已重寫它。這返回異常的原因。

廣告