一、基本概念
異常(Exception):程序執行過程中發生的非正常情況,比如除以零、訪問越界、內存不足等。
異常處理(Exception Handling):對異常情況進行捕獲、分析,并采取補救措施,防止程序崩潰。
C++ 采用 try-catch 語句塊配合 throw 來實現異常處理:
try 塊:放置可能拋出異常的代碼。
throw:用于拋出異常對象。
catch 塊:用于捕獲異常并處理。
二、語法結構
try {// 可能拋出異常的代碼if (something_wrong) {throw exception_object; // 拋出異常}
}
catch (ExceptionType1 e1) {// 處理 ExceptionType1 類型的異常
}
catch (ExceptionType2 e2) {// 處理 ExceptionType2 類型的異常
}
catch (...) {// 捕獲所有未明確捕獲的異常
}
throw 后面可以是任意類型:內置類型(如 int)、字符串、用戶自定義類等。
catch 塊會根據異常的類型選擇匹配的處理器。
catch (…) 是通配符,表示捕獲所有未被前面 catch 捕獲的異常。
注:
- 推薦拋出類或結構體:最好拋出異常類,而不是基礎類型,比如用 std::runtime_error、std::invalid_argument、std::out_of_range 等。
- 按引用捕獲:為了避免拷貝,catch 中最好用引用捕獲異常。
- 異常必須處理:如果異常未被捕獲,程序會調用 std::terminate(),導致程序異常終止。
- 嵌套異常與重新拋出:可以在 catch 里再次 throw 把異常往外傳遞。
三、異常示例
小試牛刀:
#include <iostream>
#include <stdexcept> // 引入標準異常頭文件using namespace std;int divide(int a, int b) {if (b == 0) {throw runtime_error("Division by zero!"); // 拋出標準運行時異常}return a / b;
}int main() {try {int result = divide(10, 0); // 這里會拋出異常cout << "Result: " << result << endl;} catch (const runtime_error& e) { // 用引用捕獲標準異常cout << "Caught exception: " << e.what() << endl;}cout << "Program continues..." << endl;return 0;
}
輸出結果:
工程中常見的處理
#include <iostream>
#include <stdexcept>
#include <string>using namespace std;// 錯誤碼枚舉
enum class ErrorCode {InvalidArgument = 1001,ZeroValue = 1002,OutOfRange = 1003
};// 自定義異常類
class MyError : public exception {
private:string message;ErrorCode code;string file;int line;public:MyError(const string& msg, ErrorCode c, const string& f, int l): message(msg), code(c), file(f), line(l) {}// 重寫 what() 方法,返回錯誤信息const char* what() const noexcept override {return message.c_str();}ErrorCode getCode() const noexcept {return code;}const string& getFile() const noexcept {return file;}int getLine() const noexcept {return line;}
};// 用宏封裝 throw,自動帶文件名和行號
#define THROW_MYERROR(msg, code) throw MyError(msg, code, __FILE__, __LINE__)// 拋異常的函數
void doSomething(int value) {if (value < 0) {THROW_MYERROR("Value must be non-negative!", ErrorCode::InvalidArgument);} else if (value == 0) {THROW_MYERROR("Value must not be zero!", ErrorCode::ZeroValue);} else if (value > 100) {THROW_MYERROR("Value out of valid range!", ErrorCode::OutOfRange);}cout << "doSomething succeeded." << endl;
}int main() {try {doSomething(-5); // 會觸發 InvalidArgument}catch (const MyError& e) {cout << "Caught MyError: " << e.what() << endl;cout << "Error code: " << static_cast<int>(e.getCode()) << endl;cout << "File: " << e.getFile() << endl;cout << "Line: " << e.getLine() << endl;}cout << "Program continues..." << endl;return 0;
}
輸出結果: