《Effective C++》條款8:關於解構函式異常捕捉的問題
阿新 • • 發佈:2020-12-04
本章節主要描述了解構函式異常捕捉的問題;
對於C++來說,有一條重要的異常捕捉規定:所以異常都可以丟擲,但是不可以在解構函式內進行傳播;
所以對於解構函式,一定要注意異常問題,要麼捕捉,要麼強行結束;
但是由於程式強制結束並不科學,所以一邊採用捕捉的方式來進行處理;
但是一旦出現異常,必定意味著程式的執行出現了問題,往往最好的辦法還是先用普通函式判斷,最後在解構函式進行異常捕捉;
對於典型的案例,有資料庫連線的問題;
class DBConnection { public: static DBConnection create(); void close(); }; class DBConn { public: ~DBConn() { db.close(); } private: DBConnection db; };
如上所示,典型的資料庫連線問題,其中DBConnection為一個連線類,DBConn為控制類,控制DBConnection的連線和釋放;
但是存在問題的是,db.close()可能會呼叫失敗,所以根據解構函式異常捕捉原則,我們採用兩種方法進行;
使用abort()來解決:
class DBConn { public: ~DBConn() { db.close(); std::abort(); } private: DBConnection db; };
abort()的功能在於,如果丟擲異常,不等異常傳播,直接中斷和結束所有程式執行;
這種方法比較無腦,違反了一般的程式邏輯控制思維;
使用try-catch來進行異常抓取:
class DBConn { public: ~DBConn() { try { db.close(); } catch(exception){ //對log日誌進行記錄,並且進行相關操作; } } private: DBConnection db; };
類似的操作有點像JAVA中的操作,抓取異常並且進行處理;
個人疑惑點:
對於書中的一點意見不太理解,try_catch完全可以在catch中對後續行為做出定義,為什麼不能進行補救措施?
也可以對介面進行優化,採用“雙保險”措施:
書中給出的案例是採用兩次操作判定來減少這類情況的產生;
例如,對於database的連線,完全可以先關一次,最後解構函式再關一次;
class DBConn { public: void close() { db.close(); closed = true; } ~DBConn() { if (!closed) { try { db.close(); } catch (exception) { //繼續log日誌記錄; } } } private: DBConnection db; bool closed; };
s
針對於解構函式異常的捕捉,可以“對於解構函式中可能出現異常的操作,先定義普通成員函式進行操作,而後在解構函式中進行tray-catch二次判斷”;