這節(jié)和異常有關(guān),這一塊是我不太熟悉的,只能先把自己理解的記錄下來。
1 class Widget
2 {
3 public:
4
5 ~Widget() {} //假設(shè)這里會吐出一個異常
6 };
7
8 void doSomething()
9 {
10 std::vector v;
11
12 }//v在這里自動銷毀
上面的代碼中,假設(shè)v含有10個Widget,如果在前面幾個的析構(gòu)函數(shù)中彈出異常,則程序會過早結(jié)束或者出現(xiàn)不明確行為。
確實不鼓勵在析構(gòu)函數(shù)中拋出異常,可是如果程序在析構(gòu)函數(shù)中必須執(zhí)行一個動作,加入收藏而該動作可能會在失敗時拋出異常,該怎么辦呢?比如下例:
1 class DBConnection
2 {
3 public:
4 static DBConnection create();
5 void close();//關(guān)閉連接,失敗則拋出異常
6 };
為了確保用戶不忘記調(diào)用close()關(guān)閉連接,我們可以創(chuàng)建一個管理DBConnection資源的類:
1 class DBConn
2 {
3 public:
4 ~DBConn()
5 {
6 db.close();
7 }
8 private:
9 DBConnection db;
10 };
這樣在使用時,如果close沒有異常,則會很完美,不然DBConn就會使得它離開close函數(shù),這會出現(xiàn)上述問題。
我們可以在DBConn的析構(gòu)函數(shù)中,自己提前處理這個異常,但是這么做對于“導(dǎo)致close拋出異?!钡那闆r無法做出反應(yīng)。
一個比較好的策略是重新定義DBConn接口,給用戶一個機會自己處理這種異常,比如,給用戶定義一個函數(shù)close:
1 class DBConn
2 {
3 public:
4 void close()//讓用戶有機會自己捕捉異常
5 {
6 db.close();
7 closed = true;
8 }
9
10 ~DBConn()
11 {
12 if(!closed)
13 {
14 try{
15 db.close();
16 }
17 catch(){
18 //記錄下對close的調(diào)用失敗
19 }
20 }
21 private:
22 DBConnection db;
23 bool closed;
24 };
這樣一來,就有了雙保險,用戶可以自己處理異常,如果他們不處理,則析構(gòu)函數(shù)會自動吞下異常。
總結(jié):
1.在析構(gòu)函數(shù)中盡可能不要吐出異常,如果真要吐出就在析構(gòu)函數(shù)中捕獲所以的異常,并提前結(jié)束程序或吞下它們;
2.如果用戶需要自己處理異常,則在類中應(yīng)該提供一個普通函數(shù)處理。
1 class Widget
2 {
3 public:
4
5 ~Widget() {} //假設(shè)這里會吐出一個異常
6 };
7
8 void doSomething()
9 {
10 std::vector
11
12 }//v在這里自動銷毀
上面的代碼中,假設(shè)v含有10個Widget,如果在前面幾個的析構(gòu)函數(shù)中彈出異常,則程序會過早結(jié)束或者出現(xiàn)不明確行為。
確實不鼓勵在析構(gòu)函數(shù)中拋出異常,可是如果程序在析構(gòu)函數(shù)中必須執(zhí)行一個動作,加入收藏而該動作可能會在失敗時拋出異常,該怎么辦呢?比如下例:
1 class DBConnection
2 {
3 public:
4 static DBConnection create();
5 void close();//關(guān)閉連接,失敗則拋出異常
6 };
為了確保用戶不忘記調(diào)用close()關(guān)閉連接,我們可以創(chuàng)建一個管理DBConnection資源的類:
1 class DBConn
2 {
3 public:
4 ~DBConn()
5 {
6 db.close();
7 }
8 private:
9 DBConnection db;
10 };
這樣在使用時,如果close沒有異常,則會很完美,不然DBConn就會使得它離開close函數(shù),這會出現(xiàn)上述問題。
我們可以在DBConn的析構(gòu)函數(shù)中,自己提前處理這個異常,但是這么做對于“導(dǎo)致close拋出異?!钡那闆r無法做出反應(yīng)。
一個比較好的策略是重新定義DBConn接口,給用戶一個機會自己處理這種異常,比如,給用戶定義一個函數(shù)close:
1 class DBConn
2 {
3 public:
4 void close()//讓用戶有機會自己捕捉異常
5 {
6 db.close();
7 closed = true;
8 }
9
10 ~DBConn()
11 {
12 if(!closed)
13 {
14 try{
15 db.close();
16 }
17 catch(){
18 //記錄下對close的調(diào)用失敗
19 }
20 }
21 private:
22 DBConnection db;
23 bool closed;
24 };
這樣一來,就有了雙保險,用戶可以自己處理異常,如果他們不處理,則析構(gòu)函數(shù)會自動吞下異常。
總結(jié):
1.在析構(gòu)函數(shù)中盡可能不要吐出異常,如果真要吐出就在析構(gòu)函數(shù)中捕獲所以的異常,并提前結(jié)束程序或吞下它們;
2.如果用戶需要自己處理異常,則在類中應(yīng)該提供一個普通函數(shù)處理。