位置:首頁 > 高級語言 > C++教學 > C++異常處理

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>,可以在程序中使用定義的標準異常列表。這些被組織在以下所示的父子類層次結構:

C++異常層次結構
這是在上麵提到的層次結構每個異常的小說明:
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()是異常類提供一個公共方法,它已被所有子異常類覆蓋。這將返回一個異常的原因。