析構函數若拋出異常,在堆疊展開期間若再有另一異常被拋出,程序會直接調用 std::terminate 終止。標準庫容器(如 vector<Widget>)銷毀元素時,若某元素析構拋出異常,其餘元素將不再被析構,導致資源洩漏或狀態不一致。
class Widget {
public:
~Widget() { /* 可能拋出異常 */ }
};
void doSomething() {
vector v(10);
// v 析構時逐個銷毀 Widget,若第 3 個拋出異常,第 4~10 個不再析構
}
~DBConn() {
try { db.close(); }
catch (...) {
logError("DBConn::close failed");
// 吞下異常,不傳播
}
}
~DBConn() {
try { db.close(); }
catch (...) {
logError("DBConn::close failed");
std::abort(); // 立即終止
}
}
提供顯式 close() 函數供客戶端調用,析構函數僅作保底:
class DBConn {
public:
void close() { /* 可能拋出,客戶端決定如何處理 */ }
~DBConn() {
if (!closed) {
try { close(); }
catch (...) { std::abort(); } // 保底
}
}
private:
bool closed = false;
DBConnection db;
};
析構函數絕對不要吐出異常;若調用的函數可能拋出,應捕獲並吞下或終止程序。
若客戶需對操作失敗做出反應,類別應提供普通函數(非析構函數)執行該操作。