經驗1:
析構函數絕對不要吐出異常。如果一個被析構函數調用的函數可能拋出異常,析構函數應該捕捉任何異常,然後吞下它們(不傳播)或結束程序。
示例:
class DBConnection{ public: static DBConnection create(); //返回DBConnection對象 void close(); }; class DBConn{ //這個class用來管理DBConnection對象 public: ~DBConn(){ //確保數據庫連接總是會被關閉 try{ db.close();} catch(Exception e){ //制作運轉記錄,記下對close的調用失敗 //1.調用abort結束程序,阻止異常從析構函數傳播出去, //那樣會導致不明確的行為 std::abort(); //2.或者可以選擇不調用std::abort()函數,直接吞下異常 } } private: DBConnection db; };
經驗2:
如果客戶需要對某個操作函數運行期間拋出的異常做出反應,那麼class應該提供一個普通函數(而非在析構函數中)執行該操作。
示例:
class DBConnection{ public: static DBConnection create(); //返回DBConnection對象 void close(); }; class DBConn{ //這個class用來管理DBConnection對象 public: void close() //雙重保險。客戶可以自己選擇如何處理錯誤 { db.close(); closed = true; } ~DBConn(){ //確保數據庫連接總是會被關閉 try{ db.close();} catch(Exception e){ //制作運轉記錄,記下對close的調用失敗 //1.調用abort結束程序,阻止異常從析構函數傳播出去, //那樣會導致不明確的行為 std::abort(); //2.或者可以選擇不調用std::abort()函數,直接吞下異常 } } private: DBConnection db; bool closed; };