認識C 異常處理

2021-08-19 22:14:16 字數 4382 閱讀 1782

c++的異常處理機制是用於將執行時錯誤檢測和錯誤處理功能分離的一種機制(符合高內聚低耦合的軟體工程設計要求), 這裡主要總結一下c++異常處理的基礎知識, 包括基本的如何引發異常(使用throw)和捕獲異常(try catch)相關使用注意點, 以及c++標準庫提供的一套標準異常類和這些異常類的繼承層級結構以及相關使用方法和常用習慣.

throw: 當問題出現時,程式會丟擲乙個異常。這是通過使用 throw 關鍵字來完成的。

catch: 在您想要處理問題的地方,通過異常處理程式捕獲異常。catch 關鍵字用於捕獲異常。

try: try 塊中的**標識將被啟用的特定異常。它後面通常跟著乙個或多個 catch 塊。

如果有乙個塊丟擲乙個異常,捕獲異常的方法會使用 try 和 catch 關鍵字。try 塊中放置可能丟擲異常的**,try 塊中的**被稱為保護**。使用 try/catch 語句的語法如下所示:

try

catch( exceptionname e1 )

catch( exceptionname e2 )

catch( exceptionname en )

如果 try 塊在不同的情境下會丟擲不同的異常,這個時候可以嘗試羅列多個 catch 語句,用於捕獲不同型別的異常。

void func()

catch(datatype1& d1)

catch(datatype2& d2)

catch(datatype3& d3)

catch(…)

}

注意上面try block中可能丟擲的datatype1datatype2datatype3三種型別的異常物件在前面都已經有對應的catch block來處理。但為什麼還要在最後再定義乙個catch(…) block呢?這就是為了有更好的安全性和可靠性,避免上面的try block丟擲了其它未考慮到的異常物件時導致的程式出現意外崩潰的嚴重後果

引發c++異常的語法就是使用throw語句:throw object;注意這裡throw丟擲的是乙個物件,也就是說是乙個例項。一旦丟擲,發生兩件事情:第一,c++異常機制開始尋找try catch模組,尋找和丟擲的物件的型別相匹配的catch子句找到處理**進行異常的處理,這個過程是乙個棧展開的過程,也就是說c++講先從當前的函式體裡面尋找try catch模組,如果沒有,則在呼叫當前函式(比如我們叫當前函式a)的函式(我們叫呼叫a的函式b)尋找處理**(在b裡面尋找),一直尋找直到找到匹配的catch子句,然後執行catch裡面的**,執行完畢以後,從這個匹配的catch後面的**繼續執行。第二,棧展開前面的所有函式作用域都失效(比如, a呼叫b,b呼叫c,c呼叫d,d呼叫e,e丟擲異常同時在c找到了處理異常的catch子句,那麼d,e作用域失效,等效於d,e執行到了函式結尾),區域性物件(自動釋放記憶體的物件,而不是那些動態分配記憶體的物件,這一點和異常安全都將呼叫析構函式進行銷毀。throw是乙個c++關鍵字,與其後的運算元構成了throw語句,語法上類似於return語句,您可以使用throw 語句在**塊中的任何地方丟擲異常。throw 語句的運算元可以是任意的表示式,表示式的結果的型別決定了丟擲的異常的型別。以下是嘗試除以零時丟擲異常的例項:

double division(int a, int b)

return (a/b);

}

如果要試圖捕獲c++異常, 那麼將可能丟擲(throw)異常的**塊放到try{}裡面, 在try{} 後面跟上catch(exception e) {}, 這裡的e是一般的異常物件, c++異常處理通過丟擲物件的型別來判斷決定啟用哪個catch處理**. 具體語法可以參見任何一本c++的書籍. 這裡主要提幾點注意點:

1. 講throw的時候也提到了, catch是一層一層catch(棧展開), 當尋找到main裡面也沒有catch捕獲的時候, c++機制一般將呼叫terminate終止程序(abort)。

2. catch子句列表中, 最特殊的catch必須最先出現, 不然永遠都不可能執行到。

3. catch(…) 這個語法表示catch捕獲所有異常。

4. 在catch裡面使用throw ;這條語句將重新丟擲異常物件, 改異常物件是和捕獲的一場物件同乙個物件(catch中可以修改這個物件)。

try

catch( exceptionname e )

上面的**會捕獲乙個型別為exceptionname的異常。如果您想讓 catch 塊能夠處理 try 塊丟擲的任何型別的異常,則必須在異常宣告的括號內使用省略號 …,如下所示:

try

catch(...)

下面是乙個例項,丟擲乙個除以零的異常,並在 catch 塊中捕獲該異常。

#include 

using

namespace

std;

double division(int a, int b)

return (a/b);

}int main ()

catch (const

char* msg)

return

0;}

由於我們丟擲了乙個型別為const char*的異常,因此,當捕獲該異常時,我們必須在 catch 塊中使用const char*。當上面的**被編譯和執行時,它會產生下列結果:

division by zero condition!

c++ 提供了一系列標準的異常,定義在 中,我們可以在程式中使用這些標準的異常。它們是以父子類層次結構組織起來的,如下所示:

下表是對上面層次結構中出現的每個異常的說明:

異常描述

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

當發生數學下溢時,會丟擲該異常。

您可以通過繼承和過載 exception 類來定義新的異常。下面的例項演示了如何使用 std::exception 類來實現自己的異常:

#include 

#include

using

namespace

std;

struct myexception : public exception

};int main()

catch(myexception& e)

catch(std::exception& e)

}

這將產生以下結果:

myexception caught

c++ exception

在這裡,what() 是異常類提供的乙個公共方法,它已被所有子異常類過載。這將返回異常產生的原因。

c++異常處理解析1: 異常的引發(throw), 捕獲(try catch), 標準異常等

c++異常處理解析2: 異常安全(記憶體洩露, 空指標等問題)

c++異常處理解析3: 錯誤處理(返回值, 錯誤標誌變數, 異常)各有千秋

Java 異常處理的重要認識

exception 一般標識的是程式中出現的問題,可以直接使用try catch處理。error 一般值得是jvm錯誤,程式中無法處理。檢測異常類需要在throws後面羅列,但是不檢測異常類不需要在throws後面羅列。丟擲異常,等價於生成該異常類的物件,作為引數傳遞給catch exception...

C 異常處理

結構化異常 structured exception vs c 異常 c exception 大家都知道c 異常是c 語言的乙個特性,使用者可以使用throw的方式來丟擲異常,try catch 來捕獲異常。結構化異常是諸如,zero divided,access violations等異常,這些異...

c 異常處理

一 概述 c 自身有著非常強的糾錯能力,發展到如今,已經建立了比較完善的異常處理機制。c 的異常情況無非兩種,一種是語法錯誤,即程式中出現了錯誤的語句,函式,結構和類,致使編譯程式無法進行。另一種是執行時發生的錯誤,一般與演算法有關。關於語法錯誤,不必多說,寫 時心細一點就可以解決。c 編譯器的報錯...