try {
// 可能拋出異常的代碼
} catch (const ExceptionType1& e) {
// 處理 ExceptionType1 及其派生類
} catch (const ExceptionType2& e) {
// 處理 ExceptionType2
} catch (...) {
// 捕獲所有其他異常(最後兜底)
}
throw expr:拋出異常對象(拷貝/移動構造到異常存儲區)catch (Type name):按類型匹配,**派生類先於基類**捕獲catch (...):捕獲任意類型,常用於日誌/清理後重拋catch 子句,進入處理塊catch 結束後,異常對象銷毀catch,調用 std::terminate⚠️ **析構函數中不可拋出異常**(C++11 起隱含 noexcept),否則雙重異常導致 terminate。
std::exception ├── std::logic_error // 邏輯錯誤(可預防) │ ├── std::invalid_argument // 無效參數 │ ├── std::domain_error // 域錯誤(數學) │ ├── std::length_error // 長度超限 │ └── std::out_of_range // 越界 ├── std::runtime_error // 運行時錯誤(難預防) │ ├── std::range_error // 範圍錯誤 │ ├── std::overflow_error // 上溢 │ └── std::underflow_error // 下溢 ├── std::bad_alloc // new 失敗 ├── std::bad_cast // dynamic_cast 失敗 ├── std::bad_typeid // typeid 失敗 ├── std::bad_exception // unexpected_handler 拋出 └── std::ios_base::failure // IO 流錯誤
所有標準異常提供 virtual const char* what() const noexcept 返回錯誤描述。
class NetworkError : public std::runtime_error {
int errorCode;
std::string endpoint;
public:
NetworkError(int code, const std::string& ep, const std::string& msg)
: std::runtime_error(msg), errorCode(code), endpoint(ep) {}
int code() const noexcept { return errorCode; }
const std::string& endpoint() const noexcept { return endpoint; }
};
// 使用
void connect(const std::string& host) {
if (!reachable(host))
throw NetworkError(ETIMEDOUT, host, "Connection timeout");
}
原則:繼承 std::exception 或其派生類;提供豐富診斷信息;保證拷貝/移動構造不拋異常(noexcept)。
void foo() noexcept; // 承諾不拋出(違反 → terminate) void bar() noexcept(false); // 可能拋出(默認) // C++17 noexcept 成為類型系統一部分:noexcept(foo()) 為常量表達式
try {
risky();
} catch (const NetworkError& e) {
log(e);
if (!canRecover(e)) throw; // 原封不動重拋,保持類型與棧跡蹤
}
| 等級 | 保證 | 典型實現 |
|---|---|---|
| 無保證 | 可能洩漏資源、破壞不變量 | 裸指針手動管理 |
| 基本保證 | 不洩漏資源、對象保持有效狀態(但狀態可能改變) | 智能指針、RAII |
| 強保證 | 操作要么成功要么回滾到原狀態(事務語義) | Copy-and-swap、事務日誌 |
| 不拋出保證 | 絕不拋出異常 | 析構函數、swap、移動操作 |
核心思想:資源獲取即初始化,析構函數釋放資源。棧展開自動調用析構,**天然實現異常安全**。
void processFile(const std::string& path) {
std::ifstream in(path); // 構造打開,析構自動關閉
std::unique_ptr buf = std::make_unique(1024);
// 任何拋出異常,in/buf 確定釋放
parse(in, *buf);
}
std::expected/錯誤碼;不可預期/嚴重錯誤用異常std::source_location:捕獲文件/行/函數信息,豐富異常上下文std::exception_ptr:跨線程傳遞異常std::expected<T, E> (C++23):無異常錯誤處理單子noexcept 推導改進、模板異常規範