C++ 异常处理是一种机制,用于在程序执行期间处理运行时错误或其他异常情况。它允许程序在遇到错误时执行特定的代码块,而不是立即终止执行。异常处理通过 try, catch, 和 throw 关键字来实现。
基本结构
一个基本的异常处理结构包括 try 块和至少一个 catch 块。try 块包含可能会抛出异常的代码,而 catch 块则处理这些异常。
cpp复制代码
|
try { |
|
// 尝试执行的代码,可能会抛出异常 |
|
throw ExceptionType(some_value); // 抛出异常 |
|
} catch (const ExceptionType& e) { |
|
// 处理异常 |
|
std::cerr << "Caught an exception: " << e.what() << std::endl; |
|
} |
抛出异常
使用 throw 关键字可以抛出一个异常。抛出的可以是任何数据类型,但最好是使用标准库中的异常类,或者自定义的异常类。
cpp复制代码
|
throw std::runtime_error("A runtime error occurred"); |
捕获异常
catch 块用于捕获异常。它可以指定要捕获的异常类型。可以有多个 catch 块来捕获不同类型的异常。
cpp复制代码
|
try { |
|
// ... 可能抛出异常的代码 ... |
|
} catch (const std::runtime_error& e) { |
|
// 处理 std::runtime_error 类型的异常 |
|
} catch (const std::exception& e) { |
|
// 处理所有 std::exception 及其派生类类型的异常 |
|
} catch (...) { |
|
// 处理所有类型的异常(万能捕获) |
|
} |
异常规格(Exception Specifications)
在函数声明中,可以使用异常规格来指定函数可能抛出的异常类型。这在 C++11 及之前的版本中是一个特性,但在 C++17 中被弃用,并在 C++20 中被移除。现代 C++ 实践通常不推荐使用异常规格。
自定义异常类
你可以通过继承标准异常类(如 std::exception)来创建自定义异常类。这允许你添加额外的成员变量和成员函数来提供更详细的错误信息。
cpp复制代码
|
class MyCustomException : public std::exception { |
|
private: |
|
std::string message; |
|
public: |
|
MyCustomException(const std::string& msg) : message(msg) {} |
|
virtual const char* what() const throw() { |
|
return message.c_str(); |
|
} |
|
}; |
|
|
|
try { |
|
throw MyCustomException("A custom error occurred"); |
|
} catch (const MyCustomException& e) { |
|
std::cerr << "Caught a custom exception: " << e.what() << std::endl; |
|
} |
使用异常处理的好处
· 错误处理分离:异常处理允许将错误处理代码与正常流程代码分离,使代码更加清晰。
· 错误传播:异常可以自动传播到调用栈的上层,而不需要每个函数都显式检查错误条件。
· 资源清理:在 try 块中分配的资源可以在 catch 块中安全地清理,即使在发生异常的情况下也是如此。这通常通过使用 RAII(Resource Acquisition Is Initialization)技术来实现。
注意事项
· 避免过度使用:不是所有错误情况都适合使用异常处理。在某些情况下,使用返回值或错误码可能更合适。
· 避免在析构函数中抛出异常:析构函数在对象生命周期结束时自动调用,如果在析构函数中抛出异常且未被捕获,程序将调用 std::terminate 并立即终止。
· 性能考虑:异常处理有一定的性能开销,因此,在性能敏感的代码中应谨慎使用。
总的来说,C++ 异常处理是一种强大的机制,用于处理运行时错误和其他异常情况。它允许程序在发生错误时保持结构化和可维护性,同时提供了一种清晰的错误处理模式。