简体   繁体   English

捕获C ++基本异常

[英]Catching c++ base exceptions

In my project we have a base exception. 在我的项目中,我们有一个基本例外。 For handling showing error dialogs, log and such. 为了处理显示错误对话框,日志等。 Im looking for a way to handle all derived classes of that exception, I thought this would work: 我正在寻找一种处理该异常的所有派生类的方法,我认为这会起作用:

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

As every child instance thrown could be represented by a pointer to its parent. 由于抛出的每个子实例都可以通过指向其父实例的指针来表示。 But no, when exceptions are thrown now, its an unhandled exception. 但是不,现在抛出异常时,它是未处理的异常。

Why is this? 为什么是这样? Do c++ only throw exceptions as references? c ++仅将异常作为引用抛出吗? Thereby rendering my catch block useless? 从而使我的捕获块无用? But then why does this even compile in the first place? 但是,为什么还要首先编译呢?

The only other way I can think of is this: 我能想到的唯一其他方法是:

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

Which seems kinda ugly. 这似乎有点丑陋。 What is the correct way to do this? 正确的方法是什么? Dont have a base exception class? 没有基础异常类? Or can it be solved in the way I want? 还是可以按照我想要的方式解决?

Ps: What handle_error() does is simply make use of the base class function display_message_box() and cleanly shutdown the program. handle_error()handle_error()作用仅仅是使用基类函数display_message_box()并完全关闭程序。

Just mix the two approaches: use the base class, and use a reference. 只需混合两种方法:使用基类,并使用引用。

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

BTW C++ can catch pointers, if you throw them. BTW C ++可以捕获指针(如果将其抛出)。 It's not advisable though. 但是不建议这样做。

Your best bet is to catch the base reference. 最好的选择是抓住基本参考。 But please do so by reference, not by pointer. 但是请通过引用而不是通过指针进行操作。 Example

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

The problem with catching an exception by pointer is that it must be thrown by pointer. 通过指针捕获异常的问题是必须由指针抛出异常。 This means that it will be created with new. 这意味着将使用new创建它。

throw new ExceptionA();

This leaves a rather large problem because it must be deleted at some point or you have a memory leak. 这留下了一个相当大的问题,因为必须在某个时候将其删除,否则就会发生内存泄漏。 Who should be responsible for deleting this exception? 谁负责删除此异常? It's generally difficult to get this right which is why most people catch by reference. 通常很难做到这一点,这就是为什么大多数人都通过引用来了解。

In general in C++ you should ... 一般来说,在C ++中,您应该...

Catch by reference, throw by value 按参考捕捉,按价值抛出

You can only use catch( const sometype* ptr ) if you are throwing pointers, which is inadvisable under 99% of circumstances. 如果要抛出指针,则只能使用catch( const sometype* ptr ) ,这在99%的情况下是不建议的。

The reason catch( const sometype& ptr ) works is because r-values are implicitly convertible to constant references. catch( const sometype& ptr )之所以起作用,是因为r值可以隐式转换为常量引用。

This should work: 这应该工作:

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

I assume ExceptionA/B/C all inherit from MyExceptionBase...I think that should work just fine. 我假设ExceptionA / B / C都继承自MyExceptionBase ...我认为应该可以正常工作。

PS: you may want to consider having MyExceptionBase inhert from std::exception as well. PS:您可能还想考虑从std :: exception继承MyExceptionBase。

I am surprised that your original example doesn't work. 令您惊讶的是您原来的示例不起作用。 The following does work (at least with g++): 确实可以使用以下功能(至少在g ++中有效):

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

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

I'm also pretty sure that this is intended to work as per a bullet under 15.3/3: 我也很确定这可以按照15.3 / 3下的项目符号工作:

the handler is of type cv1 T* cv2 and E is a pointer type that can be converted to the type of the handler by either or both of 处理程序的类型为cv1 T * cv2,E是指针类型,可以通过以下任意一个或全部将其转换为处理程序的类型

Are you inheriting from the base exception type via public inheritance? 您是否要通过公共继承从基本异常类型继承? The base class needs to be an accessible base and this would stop your exception from being caught. 基类必须是可访问的基类,这将阻止您的异常被捕获。

As per all the other answers here, throwing/catching by reference has an advantage in that you do not need to worry about ownership of the memory etc. But if the example above doesn't work - then I don't know why the reference example would work. 根据这里所有其他答案,按引用抛出/捕获有一个优点,就是您不必担心内存的所有权等。但是,如果上面的示例不起作用-那么我不知道为什么引用例子会工作。

As others have mentioned, you should catch a reference to the base class exception. 正如其他人提到的那样,您应该捕获对基类异常的引用。

As for why it compiles in the first place, unlike Java, there are no restrictions on what types can be thrown or caught. 至于为什么要首先编译,与Java不同,对于可以引发或捕获哪些类型没有任何限制。 So you can put in a catch block for any type, even if it's never thrown, and your compiler will happily compile it. 因此,即使从未抛出过任何类型,您都可以放入catch块,并且编译器会很乐意对其进行编译。 Since you can throw by pointer, you can also catch by pointer. 由于可以通过指针进行抛出,因此还可以通过指针进行捕获。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM