捕获c ++基础异常

时间:2009-02-12 12:43:54

标签: c++ exception try-catch

在我的项目中,我们有一个基本的例外。用于处理显示错误对话框,日志等。 我正在寻找一种方法来处理该异常的所有派生类,我认为这样可行:

try
{
  main_loop();
}
catch (const MyExceptionBase* e)
{
  handle_error(e);
}

因为抛出的每个子实例都可以由指向其父级的指针表示。但是,不,当现在抛出异常时,它是一个未处理的异常。

这是为什么? c ++只将异常作为引用抛出吗?从而使我的捕获块无用?但那么为什么这甚至首先编译?

我能想到的另一种方式是:

try
{
  main_loop();
}
catch (const ExceptionA& e)
{
  handle_error(e);
}
catch (const ExceptionB& e)
{
  handle_error(e);
}
catch (const ExceptionC& e)
{
  handle_error(e);
}

这看起来有点难看。这样做的正确方法是什么?没有基本的异常类?或者它能以我想要的方式解决吗?

Ps:handle_error()所做的只是使用基类函数display_message_box()并干净地关闭程序。

6 个答案:

答案 0 :(得分:16)

只需混合使用两种方法:使用基类,并使用引用。

try
{
  main_loop();
}
catch (const MyExceptionBase& e)
{
  handle_error(e);
}
如果扔掉它们,BTW C ++可以捕获指针。但这不可取。

答案 1 :(得分:15)

最好的办法是抓住基准参考。但请参考,而不是指针。实施例

try
{
  main_loop();
}
catch (const MyExceptionBase& e)
{
  handle_error(e);
}

通过指针捕获异常的问题是它必须由指针抛出。这意味着它将使用new创建。

throw new ExceptionA();

这留下了一个相当大的问题,因为它必须在某些时候被删除或者你有内存泄漏。谁应该负责删除此例外?通常很难做到这一点,这就是大多数人通过引用捕获的原因。

一般来说,在C ++中你应该......

  

按引用捕获,按值抛出

答案 2 :(得分:3)

如果你投掷指针,你只能使用catch( const sometype* ptr ),这在99%的情况下是不可取的。

catch( const sometype& ptr )起作用的原因是因为r值可以隐式转换为常量引用。

答案 3 :(得分:1)

这应该有效:

try {
  main_loop();
} catch (const MyExceptionBase &e) {
  handle_error(e);
}

我假设ExceptionA / B / C都继承自MyExceptionBase ......我认为应该可以正常工作。

PS:您可能也想考虑从std :: exception获取MyExceptionBase inhert。

答案 4 :(得分:1)

我很惊讶您的原始示例不起作用。以下工作(至少使用g ++):

class Base { public: virtual ~Base () {} };
class Derived : public Base {};

int main ()
{
  try
  {
    throw new Derived ();
  }
  catch (Base const * b)
  {
    delete b;
  }
}

我也很确定这打算按照15.3 / 3下的子弹工作:

  

处理程序的类型为cv1 T * cv2,E是一种指针类型,可以通过其中一个或两个转换为处理程序的类型

您是通过公共继承继承基本异常类型吗?基类需要是一个可访问的基础,这将阻止您的异常被捕获。

根据这里的所有其他答案,通过引用投掷/捕获有一个优点,因为您不需要担心内存的所有权等。但如果上面的示例不起作用 - 那么我不知道为什么参考例会起作用。

答案 5 :(得分:0)

正如其他人所提到的,你应该捕获对基类异常的引用。

至于为什么它首先编译,与Java不同,对于可以抛出或捕获的类型没有限制。所以你可以为任何类型放入一个catch块,即使它从未被抛出,你的编译器也会乐意编译它。由于你可以通过指针抛出,你也可以通过指针捕获。