- 异常处理概述 - try-catch 块 - throw 语句 - catch 的类型匹配 - 异常传播 - 标准异常 - 自定义异常 - 异常规范与 noexcept - 异常与性能 - 异常与断言 - 未捕获异常的处理 - 最佳实践 --- ### 异常处理概述 - **定义**:异常是程序运行时发生的意外问题或错误。 - **目的**:优雅地处理错误,防止程序崩溃。 - **优势**: - 强制错误处理 - 错误处理与正常代码分离 - 堆栈展开机制 --- ### try-catch 块 - **try 块**:包含可能引发异常的代码。 - **catch 块**:捕获并处理异常。 **语法**: ```cpp try { // 可能引发异常的代码 } catch (ExceptionType e) { // 异常处理代码 } ``` **示例代码**: ```cpp try { int result = 10 / 0; // 非定义行为 throw 0;// 抛出异常 } catch (std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } ``` --- ### throw 语句 - **定义**:`throw` 用于在代码中显式地引发一个异常。 - **语法**:`throw expression;`。 - **特点**: - 可以抛出任何类型的对象,但建议抛出标准异常类或其派生类。 - 异常对象的类型决定了它能被哪个 `catch` 块捕获。 **示例**: ```cpp void divide(int a, int b) { if (b == 0) { throw std::runtime_error("Division by zero"); // 抛出异常 } std::cout << "Result: " << a / b << std::endl; } ``` --- ### catch 的类型匹配 **精确匹配**:异常类型与 `catch` 块的类型完全一致。 ```cpp catch (std::runtime_error& e) { std::cerr << "Caught runtime_error: " << e.what() << std::endl; } ``` --- **基类匹配**:异常类型是派生类时,可以被基类的 `catch` 块捕获。 ```cpp catch (std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } ``` **通用捕获**:使用 `catch (...)` 捕获所有类型的异常。 ```cpp catch (...) { std::cerr << "Caught unknown exception" << std::endl; } ``` **注意事项**: - `catch` 块的顺序很重要,基类的 `catch` 块应放在派生类之后。 - `catch` 块按顺序匹配,找到匹配的 `catch` 块后,后续的 `catch` 块将被忽略。 --- ### 异常传播 - **定义**:异常在调用堆栈中向上传播,直到被捕获。 - **堆栈展开**:异常发生时,自动销毁范围内的对象。 **示例**: ```cpp void func() { throw std::runtime_error("Error in func"); } void test() { func(); } int main() { try { test(); } catch (std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } } ``` --- ### 标准异常 - **标准异常类**:`std::exception` 及其派生类。 - **常见标准异常**: - `std::invalid_argument` - `std::out_of_range` - `std::runtime_error` **示例**: ```cpp std::vector
vec = {1, 2, 3}; try { int value = vec.at(10); // 抛出 std::out_of_range } catch (std::out_of_range& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } ``` --- ### 自定义异常 **定义**:派生自 `std::exception` 的类。 **示例**: ```cpp class MyException : public std::exception { public: const char* what() const noexcept override { return "My custom exception"; } }; void func() { throw MyException(); } int main() { try { func(); } catch (MyException& e) { std::cerr << "Caught custom exception: " << e.what() << std::endl; } } ``` --- ### 异常规范与 noexcept - **异常规范**:已弃用,仅保留 `noexcept`。 - **noexcept**: - `noexcept`:函数不会抛出异常。 - `noexcept(false)`:函数可能抛出异常。 **示例**: ```cpp void safeFunction() noexcept { // 不会抛出异常的代码 } void riskyFunction() noexcept(false) { // 可能抛出异常的代码 } ``` --- ### 异常与性能 - **未引发异常时**:性能开销极低。 - **引发异常时**:堆栈遍历和展开的开销。 - **建议**:在性能关键型代码中谨慎使用异常。 --- ### 异常与断言 - **断言**:用于检查始终为 true 或 false 的条件。 - **异常**:用于处理运行时可能发生的错误。 **示例**: ```cpp assert(x > 0); // 断言 if (x <= 0) { throw std::invalid_argument("x must be positive"); } ``` --- ### 未捕获异常的处理 - **默认行为**:如果异常未被捕获,程序会调用 `std::terminate`,默认情况下会调用 `std::abort` 来终止程序。 - **自定义处理**:可以通过 `std::set_terminate` 设置自定义的终止处理函数。 ```cpp void customTerminate() { std::cerr << "Uncaught exception! Terminating program." << std::endl; exit(1); } int main() { std::set_terminate(customTerminate); throw std::runtime_error("Uncaught exception"); } ``` --- ### 最佳实践 - 使用断言检查逻辑条件。 - 使用异常处理运行时错误。 - 捕获异常时尽量具体。 - 避免在析构函数中抛出异常。