Why throw at derived class catches by base?

匿名 (未验证) 提交于 2019-12-03 02:35:01

问题:

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";   } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!