天天看點

從零開始學C++之異常(三):異常與繼承、異常與指針、異正常格說明

 一、異常與繼承

如果異常類型為C++的類,并且該類有其基類,則應該将派生類的錯誤處理程式放在前面,基類的錯誤處理程式放在後面

從零開始學C++之異常(三):異常與繼承、異常與指針、異正常格說明

派生類的異常能夠被基類所捕獲,且前面的異常處理程式能夠比對的話首先catch,如果把基類的放在最前面,而且不是引用的形式,如 catch (MyException e); 那麼将會被這個所catch 到,而且在構造e 的過程會有object slicing 的問題。

二、異常與指針

抛出指針通常是一個壞主意,因為抛出指針要求在對應處理代碼存在的任意地方都存在指針所指向的對象(注意此時throw抛出時複制的是指針本身,不會去複制指針指向的内容)

從零開始學C++之異常(三):異常與繼承、異常與指針、異正常格說明

其中MyException, MyExeptionD類如上所示,現在MyExeptionD 對象是在堆上配置設定的,是以在catch 的時候還沒釋放,還可以通路到e->what(); 但需要自己在catch 末尾delete e; 假設将 throw new MyExceptionD("test exception"); 換成MyExceptionD e("test exception");throw &e;

即抛出局部對象的指針,由于在catch 時MyExeptionD 對象已經被析構了,是以通路不到e->what(); 即e是空懸指針。

還有一點是,任何類型的指針都能被void* 指針所捕獲,如果将catch (void* e);注釋打開,那麼由于排在前面,異常首先将被它所捕獲。

三、異正常格說明

1、異正常格說明的目的是為了讓函數使用者知道該函數可能抛出的異常有哪些。

可以在函數的聲明中列出這個函數可能抛擲的所有異常類型。

例如:

void fun() throw(A,B,C,D);

2、若無異常接口聲明,則此函數可以抛擲任何類型的異常。

3、不抛擲任何類型異常的函數聲明如下:

void fun() throw();

從零開始學C++之異常(三):異常與繼承、異常與指針、異正常格說明

實際上編譯會産生警告:

warning C4290: 忽略 C++ 異正常範,但訓示函數不是 __declspec(nothrow)

就是說VC++編譯器現在還不怎麼支援異正常格說明,舉個例子說,void fun(int n) throw (int, MyException, MyExceptionD); 沒有聲明double 類型的異常,但在函數内throw 1.0;  在外部catch (double) 還是會成功。

四、C++标準庫異常層次

從零開始學C++之異常(三):異常與繼承、異常與指針、異正常格說明

比如dynamic_cast 執行錯誤會産生bad_cast 異常,new 配置設定記憶體錯誤會産生bad_alloc 異常,其實這些異常類都繼承自exception類,但内部的實作都

沒有有效的代碼,隻是用來辨別目前程式産生了哪種類型的異常而已。

參考:

C++ primer 第四版

Effective C++ 3rd

C++程式設計規範