異常處理

2018-08-12 22:03 更新

異常處理

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

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

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

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

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

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

拋出異常

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

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

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

捕獲異常

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

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

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

    try
    {
       // protected code
    }catch(...)
    {
      // code to handle any exception
    }

下面是一個(gè)例子,這個(gè)例子拋出會(huì)除零異常, 我們?cè)?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)樯侠刑岢隽艘粋€(gè) const char *類(lèi)型的異常, 所以捕捉這個(gè)異常時(shí),我們必須在 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)展示如下:

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

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

定義新異常

你可以采用繼承及重寫(xiě)異常類(lèi)來(lái)。下面是示例, 顯示如何使用 std::exception 類(lèi)以標(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() 是一個(gè)異常類(lèi)提供的公共方法,所有子異常類(lèi)都覆蓋了該方法。這將返回一個(gè)異常的原因。

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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)