2009-02-12 132 views
2

在我的项目中,我们有一个基本例外。为了处理显示错误对话框,日志等。 进出口寻找一种方式来处理该异常的所有派生类,我想这会工作:捕捉C++基本例外

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

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

这是为什么? C++只会抛出异常作为引用吗?从而渲染我的catch块无用?但是为什么这甚至首先编译?

我能想到的唯一的另一种方法是这样的:

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()并干净地关闭程序。

回答

14

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

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

顺便说一句,C++可以捕获指针,如果你扔他们。但这不是可取的。

+0

我不知道引用也可以引用派生类实例,生病尝试一下,谢谢! :) – Mizipzor 2009-02-12 13:13:29

1

这应该工作:

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

我认为ExceptionA/B/C都来自MyExceptionBase继承...我认为,应该只是罚款。 PS:你可能想要考虑让MyExceptionBase从std :: exception中获取inhert。

+0

继承std :: exception是否还有其他好处? – Mizipzor 2009-02-12 13:12:31

+0

不是一个巨大的数量,也许未捕获的异常可以有一个更有意义的消息(因为许多终止处理程序输出what()成员)。 – 2009-02-12 13:19:39

14

最好的办法是找到基准参考。但是请通过引用来完成,而不是通过指针。示例

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

捕获指针异常的问题是它必须通过指针引发。这意味着它将以新的方式创建。

throw new ExceptionA(); 

这留下了一个相当大的问题,因为它必须在某个时候删除或者您有内存泄漏。谁应该负责删除此异常?通常很难做到这一点,这就是为什么大多数人通过参考获得成功的原因。

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

渔获参考,以价值

+1

+1通过引用赶上价值。谁说的 - 萨特? – 2009-02-12 14:31:06

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是一个指针类型,它可以通过

任一个或两者被转换成该处理程序的类型你是否继承通过公共继承的基础异常类型?基类需要是一个可访问的基类,这会阻止你的异常被捕获。

正如所有其他答案在这里,通过引用引发/捕获有一个优势,因为你不需要担心内存的所有权等。但如果上面的例子不起作用 - 那么我不知道为什么参考例子会起作用。

0

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

至于为什么它首先编译,与Java不同,对于可以抛出或捕获的类型没有限制。所以你可以放入任何类型的catch块,即使它从不抛出,编译器也会很高兴地编译它。既然你可以通过指针抛出,你也可以通过指针捕获。

3

如果您正在抛出指针,则只能使用catch(const sometype* ptr),在99%的情况下这是不可取的。

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