6

if I am passing object of derived class, then the derived class catch block should be invoked. But the output says that the exception is caught by the base class. Why?

#include<iostream>
using namespace std;

class Base {};
class Derived: public Base {};
int main()
{
   Derived d;
   // some other stuff
   try {
       // Some monitored code
       throw d;
   }
   catch(Base b) { 
        cout<<"Caught Base Exception";
   }
   catch(Derived d) {  //This catch block is NEVER executed
        cout<<"Caught Derived Exception";
   }
   getchar();
   return 0;
}
Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67
sam fisher
  • 183
  • 1
  • 10

3 Answers3

10

The standard says (see [except.handle]/4] of the working draft as an example, emphasis mine):

The handlers for a try block are tried in order of appearance. [ Note: This makes it possible to write handlers that can never be executed, for example by placing a handler for a final derived class after a handler for a corresponding unambiguous public base class.

This is exactly what you did in your code.
Therefore I'd say that's the intended behavior, no matter what was your expectations.

Note that you can swap the two handlers to solve the issue.

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • [deja vu](http://stackoverflow.com/a/39537680/366904) – Cody Gray - on strike Jan 08 '17 at 19:09
  • @CodyGray Interesting. I didn't remember that answer honestly, but it's funny to see that I followed more ore less the same pattern. Should I delete this one? Not a problem. – skypjack Jan 08 '17 at 19:49
  • Nah, you don't have to delete. I only saw your answer when I searched for a question to close this one as a duplicate of. Already took care of the closure, so everything is good. I just thought it might be fun to see that you're consistent. :-) – Cody Gray - on strike Jan 09 '17 at 12:25
3

There is a little to be said about this.

Firstly, it is good practice to catch exceptions by reference instead of value. This prevents slicing of the exception object in the case that it is derived. This is not specific to exceptions but a general feature of inheritance.

A description of this phenomena is discussed here

Also, as pointed out by another answer, if you insist on doing things this way you need to change the order of catches, as a derived class satisfies the base catch block. There is another way of doing this though that uses this property explicitly: Just have the base class catch everything. You can use this unless there is a very specific feature of the derived exception that needs to be treated separately

Community
  • 1
  • 1
user3684792
  • 2,542
  • 2
  • 18
  • 23
1

The catch clauses are checked in order - you get first match, not best match.

So checking the derived type first would catch that.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203