可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
For the code below, result is "EA Exception Finished", which means although we threw at derived class it caught by base class. Is it always? And if so, how can I make the derived class catches, thus "EB Exception Finished" appears?
Also I can't exactly get what does it mean by throw EB()
and catch(EA&)
. And does catch(EA&)
means the catch block gets a reference for EA object?
Sorry for my ignorance. If you recommend me a book or something to refer about exception structure, that'd be great 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:
Reason:
Upcasting
of derived class to base. and hence always getting stuck on the first catch.
回答2:
Change the order of the catch
blocks to fix that 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:
As mentioned by the standard in [except.handle] (working draft):
The handlers for a try block are tried in order of appearance. That makes it possible to write handlers that can never be executed, for example by placing a handler for a derived class after a handler for a corresponding base class.
That's exactly what you did. Interesting indeed.
Invert the handlers to solve the issue.
回答4:
Because the catch blocks check in the order you declare them.
you first catch by EA&
. EB is derived from EA, so this is a valid catch and the second catch gets ignored.
You want to have the most "specialized" exception-catch first. So if you switch the catch blocks it should work the other way.
回答5:
catch statements are inspected in order. EA&
matches, so it is used. EB&
can never be matched. You need to put the more specific catch first.
catch(EB&) // Will catch { std::cout<<"EB Exception"; } catch(EA&) // and this would catch EA objects that aren't EB. { std::cout<<"EA Exception"; }