effect C 別讓異常逃離析構函式

2021-07-29 17:42:58 字數 1892 閱讀 1957

class widget

};void dosomething()

當vector v被銷毀,它有責任銷毀內含的所有widgets。假設v內含十個widgets,而在析構第乙個元素期間,有個異常被丟擲。其他九個widgets還是應該被銷毀(否則它們儲存的任何資源都會發生洩露),因為v應該呼叫它們它們各個析構函式。但假設在那些呼叫期間,第二個widget析構函式又丟擲異常。現在有兩個同時作用的異常,這對c++來說太多了。在這兩個異常同時存在的情況下,程式若不是結束執行就是導致不明確行為。

如果析構函式必須執行乙個動作,該動作可能會失敗時丟擲異常。

使用乙個class 負責資料庫連線:

class dbconnection
為確保客戶不忘記在dbconnection物件身上呼叫close(),建立乙個用來管理dbconnection資源的class,並在析構函式中呼叫close。

class dbconn

private:

dbconnection db;

}

這便允許客戶寫出這樣的**:

如果close呼叫異常,dbconn析構函式會傳播該異常,也就是允許它離開這個析構函式。

解決:

1.如果close丟擲異常就結束程式,通常通過abort完成:

dbconn::~dbconn()

catch(...)

}

如果程式遭遇乙個「於析構期間發生的錯誤」後無法繼續執行,「強迫結束程式」是個合理選項。畢竟它可以阻止異常從析構函式傳播出去(會導致不明確的行為)。呼叫abort可以搶先制「不明確行為」於死地。

2.吞下因呼叫close而發生的異常

dbconn::~dbconn()

catch(...)}

一般而言,將異常吞掉是個壞主意,因為它壓制了「某些動作失敗」的重要資訊!

但兩者都無法對"導致close丟擲異常"的情況做出反應。

dbconn自己提供乙個close函式,因而賦予客戶乙個機會得以處理」因該操作而發生的異常「。dbconn也可以追蹤其所管理之dbconnection是否已被關閉,並在答案為否的情況下由其析構函式關閉之。這可防止遺失資料庫連線。然後如果dbconnection析構函式呼叫close失敗,我們又將退回」強迫結束程式「或」吞下異常「的老路。

class dbconn

~dbconn()

//關閉連線

catch(...) } } private: dbconnetion db; bool closed;}

把呼叫close的責任從dbconn析構函式移到dbconn客戶手上(但dbconn析構函式仍內涵乙個」雙保險「呼叫)

如果某個操作可能在失敗時丟擲異常,而又存在某種需要必須處理該異常,那麼這個異常必須來自析構函式以外的某個函式。

析構函式絕對不要吐出異常。如果乙個析構函式呼叫的函式可能丟擲異常,析構函式應該捕獲任何異常,然後吞下它們或結束程式。

如果客戶需要對某個操作函式執行期間丟擲的異常做出反應,那麼class 應該提供乙個普通函式(而非在析構函式中)執行該操作。

別讓異常逃離析構函式

c 中並不禁止析構函式吐出異常,但是並鼓勵這樣做,看下面 當vector v被銷毀時,它有責任將其中所有的widgets銷毀並且 記憶體,而在析構第乙個元素時候,析構函式會丟擲異常,但是第二個vector的時候也會丟擲異常,這對於c 來說太多了。這會導致程式不明確的行為。c 不喜歡析構函式吐出異常。...

effective c 別讓異常逃離析構函式

c 並不禁止析構函式吐出異常,但是它不鼓勵這樣做 class widget vector vec 當vec被銷毀時,他有責任銷毀其內含的所有widget 如果vec內含10個widget,在析構第乙個元素期間,有個異常被丟擲,其他9個widget還是應該被銷毀,否則他們儲存的資源都會發生洩漏 當碰到...

條款08 別讓異常逃離析構函式

總結 1.在析構函式中盡量不要有丟擲異常的事情發生,如果析構函式中丟擲了異常,析構函式應該自己捕捉這個異常,然後根據程式需要終止程式或者吞下這個異常然繼續執行程式 2.如果需要客戶對於某個操作的函式執行期間所丟擲的異常做出反應,這個時候應該將這個丟擲異常的 函式單獨寫在乙個函式中,而不是在析構函式中...