在我的项目中,我们有一个基本的例外。用于处理显示错误对话框,日志等。 我正在寻找一种方法来处理该异常的所有派生类,我认为这样可行:
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()
并干净地关闭程序。
答案 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块,即使它从未被抛出,你的编译器也会乐意编译它。由于你可以通过指针抛出,你也可以通过指针捕获。