1. 程式人生 > 實用技巧 >《Effective C++》條款8:關於解構函式異常捕捉的問題

《Effective C++》條款8:關於解構函式異常捕捉的問題

本章節主要描述了解構函式異常捕捉的問題;

對於C++來說,有一條重要的異常捕捉規定:所以異常都可以丟擲,但是不可以在解構函式內進行傳播;

所以對於解構函式,一定要注意異常問題,要麼捕捉,要麼強行結束;

但是由於程式強制結束並不科學,所以一邊採用捕捉的方式來進行處理;

但是一旦出現異常,必定意味著程式的執行出現了問題,往往最好的辦法還是先用普通函式判斷,最後在解構函式進行異常捕捉;

對於典型的案例,有資料庫連線的問題;

class DBConnection {
public:
	static DBConnection create();
	void close();
};

class DBConn {
public:
	~DBConn() {
		db.close();
	}
private:
	DBConnection db;
};

如上所示,典型的資料庫連線問題,其中DBConnection為一個連線類,DBConn為控制類,控制DBConnection的連線和釋放;

但是存在問題的是,db.close()可能會呼叫失敗,所以根據解構函式異常捕捉原則,我們採用兩種方法進行;

使用abort()來解決:

class DBConn {
public:
	~DBConn() {
		db.close();
		std::abort();
	}
private:
	DBConnection db;
};

abort()的功能在於,如果丟擲異常,不等異常傳播,直接中斷和結束所有程式執行;

這種方法比較無腦,違反了一般的程式邏輯控制思維;

使用try-catch來進行異常抓取:

class DBConn {
public:
	~DBConn() {
		try {
			db.close();
		}
		catch(exception){
			//對log日誌進行記錄,並且進行相關操作;
		}
	}
private:
	DBConnection db;
};

類似的操作有點像JAVA中的操作,抓取異常並且進行處理;


個人疑惑點:

對於書中的一點意見不太理解,try_catch完全可以在catch中對後續行為做出定義,為什麼不能進行補救措施?


也可以對介面進行優化,採用“雙保險”措施:

書中給出的案例是採用兩次操作判定來減少這類情況的產生;

例如,對於database的連線,完全可以先關一次,最後解構函式再關一次;

class DBConn {
public:
	void close() {
		db.close();
		closed = true;
	}
	~DBConn() {
		if (!closed) {
			try {
				db.close();
			}
			catch (exception) {
				//繼續log日誌記錄;
			}
		}
	}
private:
	DBConnection db;
	bool closed;
};

s

針對於解構函式異常的捕捉,可以“對於解構函式中可能出現異常的操作,先定義普通成員函式進行操作,而後在解構函式中進行tray-catch二次判斷”