異常處理

2018-08-12 22:03 更新

異常處理

異常是一個程序執(zhí)行過程中出現(xiàn)的問題。C++ 異常是對程序運(yùn)行過程中產(chǎn)生的例外情況作出的響應(yīng),比如試圖除以零。

異常提供一種方法將程序控制從一個程序的一部分轉(zhuǎn)移到另一部分。C++ 異常處理是建立在三個關(guān)鍵詞: 嘗試,捕獲和拋出之上的。

  • throw: 程序運(yùn)行出現(xiàn)問題時拋出異常。這是使用一個 throw 關(guān)鍵字實(shí)現(xiàn)的。
  • catch: 程序用異常處理器在你想要處理問題的地方捕獲異常。catch 關(guān)鍵字顯示異常的捕獲。
  • try: 一個 try 塊標(biāo)識一個可能會產(chǎn)生異常的代碼塊。緊隨其后的是一個或多個 catch 塊。

假設(shè)一個代碼塊將產(chǎn)生一個異常,結(jié)合使用 try 和 catch 關(guān)鍵詞的方法捕獲了一個異常。一個 try / catch 塊放置在可能生成一個異常的代碼周圍。在一個 try / catch 塊里面的代碼被稱為保護(hù)代碼, try / catch 的語法規(guī)則如下:

    try
    {
       // protected code
    }catch( ExceptionName e1 )
    {
       // catch block
    }catch( ExceptionName e2 )
    {
       // catch block
    }catch( ExceptionName eN )
    {
       // catch block
    }

你可以列出多個捕捉語句捕獲不同類型的異常, 以防你的 try 代碼塊在不同的情況下產(chǎn)生了不止一個異常。

拋出異常

異??梢栽诖a塊的任何地方使用拋出語句拋出。把語句的操作數(shù)確定類型的異常,可以是任何表達(dá)式,表達(dá)式的結(jié)果的類型決定了類型的異常拋出。

下面是一個例子, 在除以零條件發(fā)生時,拋出異常:

    double division(int a, int b)
    {
       if( b == 0 )
       {
      throw "Division by zero condition!";
       }
       return (a/b);
    }

捕獲異常

try 塊后的 catch 塊可以捕獲任何異常。您可以指定你需要捕獲何種類型的異常,這是由出現(xiàn)在關(guān)鍵字 catch 后邊的括號中的異常聲明確定的。

    try
    {
       // protected code
    }catch( ExceptionName e )
    {
      // code to handle ExceptionName exception
    }

上面的代碼將捕獲到一個 ExceptionName 類型的異常。如果您想要指定一個 catch 塊可以應(yīng)該處理任何在 try 代碼中產(chǎn)生的異常,你必須將一個省略號…放在 catch 后的括號中,異常聲明如下:

    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;
    }

因?yàn)樯侠刑岢隽艘粋€ const char *類型的異常, 所以捕捉這個異常時,我們必須在 catch 塊中使用const char *。如果我們編譯和運(yùn)行上面的代碼, 這將產(chǎn)生以下結(jié)果:

    Division by zero condition!

C++ 標(biāo)準(zhǔn)異常

C++ 在 <exception> 中提供了一系列標(biāo)準(zhǔn)的異常,我們可以用在我們的程序中。這些異常使用父-子分層結(jié)構(gòu)展示如下:

這是對上面提到的層次結(jié)構(gòu)中每個異常的描述:

異常 描述
std::exception 異常和所有標(biāo)準(zhǔn) C++ 異常的父類
std::bad_alloc 該異常可能會在使用 new 關(guān)鍵字時拋出。
std::bad_cast 該異??梢杂?dynamic_cast 拋出。
std::bad_exception 這是一個在 C++ 程序中處理意想不到的異常的有效手段。
std::bad_typeid 該異??梢杂?typeid 拋出。
std::logic_error 理論上可以通過閱讀代碼發(fā)現(xiàn)的異常。
std::domain_error 這是一個在數(shù)學(xué)無效域被使用時拋出的異常。
std::invalid_argument 參數(shù)非法時會拋出的異常。
std::length_error 太大的 std::string 被創(chuàng)造時,拋出異常。
std::out_of_range 可以拋出該異常的方法例如 std::vector 和 std::bitset ::operator[] ()。
std::runtime_error 理論上不能通過讀代碼檢測到的異常。
std::overflow_errorr 如果出現(xiàn)數(shù)字溢出,則拋出該異常
std::range_error 當(dāng)你試圖存儲一個超過范圍的值的時候,會拋出該異常。
std::underflow_error 如果出現(xiàn)數(shù)學(xué)下溢時,拋出該異常。

定義新異常

你可以采用繼承及重寫異常類來。下面是示例, 顯示如何使用 std::exception 類以標(biāo)準(zhǔn)的方式實(shí)現(xiàn)自己的異常:

    #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
      }
    }

這將產(chǎn)生如下的結(jié)果:

    MyException caught
    C++ 

這里,what() 是一個異常類提供的公共方法,所有子異常類都覆蓋了該方法。這將返回一個異常的原因。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號