Effective C 筆記 條款08

2022-03-06 02:25:37 字數 1753 閱讀 2707

c++並不禁止析構函式吐出異常,但它不鼓勵你這樣做。考慮如下**:

class widget //假設這個可能吐出乙個異常

5: };
6:
7:

void dosomething()

8:

當vector v被銷毀,它有責任銷毀其內含的所有widgets。銷毀第乙個丟擲異常,銷毀第二個丟擲異常…,異常對c++而言太多了。其實,在兩個異常同時存在的情況下,程式不是結束執行就是導致不明確的行為。

c++不喜歡析構函式丟擲異常,但如果你的析構函式必須執行乙個動作,而該動作可能在失敗時丟擲異常,該怎麼辦?例如你有class負責資料庫連線:

class dbconnection;

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

class dbconn

8:

private:

9:     dbconnection db ;
10: };

這樣如果使用者在某一區塊,例項化dbconn物件時,在該區塊結束時,會自動呼叫該物件的析構函式,確保該資源管理物件管理的dbconnection物件close。只要呼叫close成功,一切美好。但如果該呼叫導致異常,dbconn析構函式會傳播該異常。三個辦法可以解決這一問題:

通常通過呼叫abort完成:

2:
4:

catch(...)

8: }

如果程式遭遇乙個「於析構期間發生錯誤」後無法繼續執行,就強迫結束程式。這種方法可以阻止異常從析構函式傳播出去,呼叫abort可以搶先制「不明確行為」於死地。

2:
4:

catch(...)

8: }

一般而言,將異常吞掉是個壞主意,因為它壓制了「某些動作失敗」的重要資訊!然而有時候吞下異常也比負擔「草率結束程式」或「不明確行為帶來的風險好」。

乙個更好的策略是重新設計dbconn介面,使其客戶有機會對可能出現的問題做出反應。例如dbconn自己可以提供乙個close函式,因而賦予客戶乙個機會得以處理「因該操作而發生的異常」。dbconn也可以追蹤其所管理的物件是否已被關閉,並在答案為否的情況下有析構函式關閉。

class dbconn

9:     ~dbconn()
10:
15:

catch(...)

18:         }
19:
20:     }
21: ptivate:
22:     dbconnection db ;
23:

bool closed ;

24: };

把呼叫close的責任從dbconn析構函式轉移到客戶手上是給他們乙個處理錯誤的機會,否則它們沒機會響應。如果他們不認為這個機會有用,可以忽略,以來dbconn的析構函式呼叫close。如果真有錯誤發生——如果close的確丟擲異常——而且dbconn析構函式結束程式或吞下該異常,客戶沒有立場抱怨。

請記住:

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

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

Effective C 筆記 條款11

為什麼會出現自我賦值呢?不明顯的自我賦值,是 別名 帶來的結果 所謂 別名 就是 有乙個以上的方法指涉物件 一般而言如果某段 操作pointers或references而它們被用來 指向多個相同型別的物件 就需要考慮這些物件是否為同乙個。實際上兩個物件來自同乙個繼承體系,它們甚至不需要宣告為相同型別...

Effective C 筆記 條款09

為方便採用書上的例子,先提出問題,在說解決方案。class transaction 7 8 transaction transaction base class 的建構函式之實現9 13 14 class buytransaction public transaction 假設在程式中 buytra...

Effective C 筆記 條款07

這個規則只適用於polymorphic 帶多型性質的 base class身上。這種base class的設計目的是為了用來 通過base class介面處理derived class物件 假如我們在程式中設計factory 工廠 函式,讓它返回base class指標,指向新生成的derived ...