Why throw in the catch of the derived class at the base?

In the code below, the result is "EA Exception Finished", which means that we threw it on a derived class that it caught with the base class. Is it always? And if so, how can I catch the derived class so that "EB Exception Finished" appears?

Also, I can’t understand exactly what this means throw EB() and catch(EA&) . And does catch(EA&) mean that the catch block gets a reference to the EA object?

Sorry for my ignorance. If you recommend a book or something to me to refer to the structure of exceptions, this will be a big help.

 class EA {}; class EB: public EA {}; void F() { throw EB(); // throw at EB(). } int main() { try { F(); } catch(EA&) // caught here?? { std::cout<<"EA Exception"; } catch(EB&) // why not me? every time? { std::cout<<"EB Exception"; } std::cout<<" Finished"<<std::endl; return 0; } 
+1
source share
5 answers

Cause:

Cast to base type

derived class to the base. and therefore always gets stuck in the first catch.

+1
source

Reorder catch blocks to fix this behavior:

 #include <iostream> class EA {}; class EB: public EA {}; void F() { throw EB(); // throw at EB(). } int main() { try { F(); } catch(EB&) // why not me? every time? { std::cout<<"EB Exception"; } catch(EA&) // caught here?? { std::cout<<"EA Exception"; } std::cout<<" Finished"<<std::endl; return 0; } 

The compiler even warns you about this:

 main.cpp:21:3: warning: exception of type 'EB' will be caught catch(EB&) // why not me? every time? ^~~~~ main.cpp:17:3: warning: by earlier handler for 'EA' catch(EA&) // caught here?? ^~~~~ 
+3
source

As stated in the standard in [except.handle] (working draft):

Handlers for the try block are checked in order of appearance. This allows you to write handlers that can never be executed, for example, by placing the handler for the derived class after the handler for the corresponding base class.

This is exactly what you did. Interesting indeed. Invert handlers to solve the problem.

+2
source

Because catch blocks check the order you declare.

you will catch EA& . EB is derived from EA, so this is a valid catch, and the second catch is ignored.

First you want to get a "specialized" exception. Therefore, if you switch catch blocks, it should work in a different way.

+1
source
Operations

catch are checked in order. EA& , therefore it is used. EB& cannot be matched. First you need to set a more specific catch.

  catch(EB&) // Will catch { std::cout<<"EB Exception"; } catch(EA&) // and this would catch EA objects that aren't EB. { std::cout<<"EA Exception"; } 
+1
source

Source: https://habr.com/ru/post/1013877/


All Articles