跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ 异常重新抛出
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C++异常重新抛出 = '''异常重新抛出'''是C++异常处理机制中的一个重要概念,它允许在当前异常处理块中捕获异常后,再次将其抛出,以便外层的异常处理块能够继续处理该异常。这一机制在多层嵌套的异常处理中尤为有用,可以实现异常的传递和分层处理。 == 基本概念 == 在C++中,当异常被抛出后,程序会沿着调用栈向上查找匹配的catch块。如果在某个catch块中需要对异常进行部分处理,但又希望外层调用者也能处理该异常,就可以使用'''重新抛出'''(rethrow)机制。重新抛出使用不带参数的throw语句: <syntaxhighlight lang="cpp"> try { // 可能抛出异常的代码 } catch (const SomeException& e) { // 部分处理 throw; // 重新抛出当前异常 } </syntaxhighlight> 关键点: * 重新抛出的是'''原始异常对象''',不会创建副本 * 只能在没有当前异常的情况下调用throw;(即在catch块外部调用会导致std::terminate) * 异常类型信息保持不变 == 代码示例 == === 基本重新抛出 === <syntaxhighlight lang="cpp"> #include <iostream> #include <stdexcept> void innerFunction() { try { throw std::runtime_error("Original error"); } catch (const std::runtime_error& e) { std::cout << "Inner caught: " << e.what() << std::endl; throw; // 重新抛出 } } int main() { try { innerFunction(); } catch (const std::runtime_error& e) { std::cout << "Outer caught: " << e.what() << std::endl; } return 0; } </syntaxhighlight> '''输出:''' Inner caught: Original error Outer caught: Original error === 异常包装示例 === 在实际应用中,常常需要将底层异常包装为高层异常: <syntaxhighlight lang="cpp"> #include <iostream> #include <stdexcept> class DatabaseException : public std::runtime_error { public: DatabaseException(const std::string& msg) : std::runtime_error(msg) {} }; void queryDatabase() { try { // 模拟数据库错误 throw std::runtime_error("SQL syntax error"); } catch (const std::runtime_error& e) { throw DatabaseException("Database operation failed: " + std::string(e.what())); } } int main() { try { queryDatabase(); } catch (const DatabaseException& e) { std::cout << "Caught: " << e.what() << std::endl; } return 0; } </syntaxhighlight> '''输出:''' Caught: Database operation failed: SQL syntax error == 异常传播流程 == <mermaid> graph TD A[抛出异常] --> B[查找匹配的catch块] B --> C{是否重新抛出?} C -->|是| D[继续向外层传播] C -->|否| E[异常处理完成] D --> F[外层catch块处理] </mermaid> == 高级主题 == === 异常指针与重新抛出 === C++允许使用std::exception_ptr来捕获和重新抛出异常,这在跨线程异常处理中特别有用: <syntaxhighlight lang="cpp"> #include <iostream> #include <exception> #include <stdexcept> void handle_exception(std::exception_ptr eptr) { try { if (eptr) { std::rethrow_exception(eptr); } } catch (const std::exception& e) { std::cout << "Handled exception: " << e.what() << '\n'; } } int main() { std::exception_ptr eptr; try { throw std::runtime_error("Error to store"); } catch (...) { eptr = std::current_exception(); } handle_exception(eptr); return 0; } </syntaxhighlight> === noexcept与重新抛出 === 在noexcept函数中重新抛出异常会导致std::terminate被调用: <syntaxhighlight lang="cpp"> #include <iostream> void riskyFunction() noexcept { try { throw std::runtime_error("Oops!"); } catch (...) { throw; // 这将导致程序终止 } } int main() { riskyFunction(); return 0; } </syntaxhighlight> == 最佳实践 == 1. '''保持异常不变性''':除非有充分理由,否则重新抛出原始异常而不是创建新异常 2. '''资源清理''':在重新抛出前确保所有资源已释放 3. '''日志记录''':考虑在重新抛出前记录异常信息 4. '''避免过度使用''':只在确实需要让外层处理时才重新抛出 == 实际应用案例 == === 中间件异常处理 === 在多层架构中,中间件可能需要捕获底层异常,添加上下文信息后重新抛出: <syntaxhighlight lang="cpp"> class Middleware { public: void process() { try { callBackend(); } catch (const BackendException& e) { logError("Backend failure in middleware"); throw ServiceException("Service unavailable", e); // 使用异常链 } } }; </syntaxhighlight> === 事务回滚 === 数据库事务处理中遇到异常时回滚并重新抛出: <syntaxhighlight lang="cpp"> void executeTransaction() { DatabaseTransaction txn; try { txn.begin(); // 执行操作... txn.commit(); } catch (...) { txn.rollback(); throw; // 重新抛出以便调用者知道事务失败 } } </syntaxhighlight> == 数学表示 == 异常重新抛出的行为可以用以下方式形式化表示: 设E为原始异常,H为处理函数,则: <math> H(E) = \begin{cases} \text{处理并终止} & \text{如果不重新抛出} \\ E & \text{如果重新抛出} \end{cases} </math> == 常见问题 == '''Q: 重新抛出会创建异常对象的副本吗?''' A: 不会,重新抛出的是原始异常对象。 '''Q: 可以在catch块之外使用throw;吗?''' A: 不可以,这会导致程序调用std::terminate()。 '''Q: 如何重新抛出并添加额外信息?''' A: 可以定义新的异常类型,在构造函数中包含原始异常(C++11起支持嵌套异常)。 [[Category:编程语言]] [[Category:C++]] [[Category:C++ 异常处理]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)