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