【问题标题】:Is it possible to write an exception type that "catches" multiple different exceptions?是否可以编写一个“捕获”多个不同异常的异常类型?
【发布时间】:2013-04-30 14:17:45
【问题描述】:

我想知道是否可以(通过巧妙的转换规则)编写一个“异常”类来帮助解决以下问题:

而不是写:

try {
 ...
} catch (std::execption const e) {    // StdLib exceptions
} catch (CException* pEx) {           // MFC exceptions
} catch (CORBA::Exception const& e) { // CORBA exceptions
} // note handling code inside catch blocks omitted for brevity

如果可以构造一个像这样工作的类型,那就太好了:

try {
  ...
} catch( magic_exception_handle const& e) { // catches all three types mentioned above
  const std::string msg = e.what(); // could also provide generalized message extraction
}

这可能吗?怎么样?

注意:我不喜欢的其他解决方案:

  • 我可以catch(...),但我确实想要包罗万象。
  • catch-handler 函数:

    void handler3() {
      try {
        throw;
      } catch (std::execption const e) {    // StdLib exceptions
      } catch (CException* pEx) {           // MFC exceptions
      } catch (CORBA::Exception const& e) { // CORBA exceptions
      } // note handling code inside catch blocks omitted for brevity
    }
    
    ...
    try { ... } catch(...) { handler3(); }
    

    也不削减它,因为虽然任何其他异常都会向外抛出,但它首先会捕获 任何 其他异常,这会导致堆栈在重新抛出之前过早展开。 (这对于在 Windows 上产生的任何崩溃转储都非常不方便。)

  • 我可以为 catch 块编写一个宏。 (

那么,是否可以创建magic_exception_handle 类型?完成了吗?

【问题讨论】:

  • 你能让这 3 个异常派生自一个公共基类吗(例如 std::exception,因为你已经注意到了)?如果是这样,您可以捕获该基类。
  • @SanderDeDycker: CException* 是一个指针——即使我疯到可以破解 MFC 源代码,我也无法让它从任何东西派生。
  • @LucTouraille:谢谢。我想这回答了这个问题。
  • @MartinBa:快速阅读标准 15.3.3 表明没有非黑客选项。回复CException* 不是从任何东西派生的......在黑客领域,您可能会被const void* 捕获并通过指向 RTTI CException 信息的初始指针识别它,但这无济于事,因为其他两种类型没有允许类似歧视的指针。

标签: c++ exception-handling multiple-inheritance virtual-inheritance


【解决方案1】:

你唯一真正的选择是颠倒逻辑:

template<typename F, typename... Args>
auto convert_exceptions(F &&f, Args... &&args)
-> decltype(f(std::forward<Args>(args)...)) {
   try {
      return f(std::forward<Args>(args)...));
   } catch (std::exception const e) {    // StdLib exceptions
      std::throw_with_nested(magic_exception{...});
   } catch (CException* pEx) {           // MFC exceptions
      std::throw_with_nested(magic_exception{...});
   } catch (CORBA::Exception const& e) { // CORBA exceptions
      std::throw_with_nested(magic_exception{...});
   }
}

你现在可以写了:

try {
   convert_exceptions([&]() {
      // ...
   });
} catch (const magic_exception &e) {
   // ...
}

【讨论】:

  • 哈! 将代码包装在一个 lambda + 对象中,该对象执行而不是编写 try-catch 块并不是一个坏主意.您的答案中不需要神奇的例外。我会将您的 convert_exception 重命名为 catch_exception 并在其中提供必要的处理程序代码,然后我就有一个可重用的 try-catch 块。 -- 好吧,如果我有一个 C++11 编译器,我会的。但我必须记住这一点。 :-)
猜你喜欢
  • 2019-05-06
  • 2018-01-04
  • 2013-01-31
  • 1970-01-01
  • 1970-01-01
  • 2010-09-13
  • 2020-05-10
  • 1970-01-01
相关资源
最近更新 更多