異常處理是 C++ 建構健壯軟體的核心機制。本文系統解析 throw 例外規格、三種異常傳遞方式(傳值、傳指標、傳參考)的優劣對比、多型行為差異、記憶體管理陷阱,並給出現代 C++ 異常處理最佳實踐建議。
void f() throw(); // 不拋出任何異常(異常安全)
void f() throw(...); // 可拋出任意異常
void f() throw(MyException); // 僅拋出 MyException 類型
注意:C++11 起 throw() 棄用,改用 noexcept;動態例外規格 C++17 移除。現代代碼請使用 noexcept / noexcept(expr)。
class MyException : public exception {
virtual const char* what() const throw() { return "myException"; }
};
void f() { throw MyException(); }
try { f(); }
catch (exception exc) { cout << exc.what(); } // 輸出 "Unknown exceptions"
問題:catch (exception exc) 觸發拷貝建構,衍生類別特有資訊被切割,呼叫基類 what() 而非衍生類別覆寫版本。不可用於多型異常體系。
void f() { throw new MyException(); }
try { f(); }
catch (exception* p) { cout << p->what(); delete p; }
優點:保持多型,正確呼叫衍生類別 what()。
缺點:
new 物件 → 何時 delete?catch 區塊?若重拋?若未捕獲?極易洩漏或雙重釋放
void f() { throw MyException(); }
try { f(); }
catch (exception& exc) { cout << exc.what(); }
優勢:
throw MyException();(值語義,非指標)catch (const BaseException& e)(const 參考,支援多型)std::exception,覆寫 what()noexcept,絕不拋出異常「以值拋出,以 const 參考捕獲」是 C++ 異常處理的黃金法則。它同時解決多型保持、物件切割、記憶體管理、效能四大核心問題。配合 RAII、noexcept、標準異常體系,能構建工業級異常安全程式碼。