Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why catch block of base class is catching the exception when I am throwing object of derived class? [duplicate]

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;
}
like image 951
sam fisher Avatar asked Jan 08 '17 13:01

sam fisher


People also ask

Will a catch statement catch a derived exception if it is looking for the base class?

Catching base and derived classes exceptions in C++ To catch an exception for both base and derive class then we need to put catch block of derived class before the base class. Otherwise, the catch block of derived class will never be reached.

What should be done if both the blocks base and derived class catch exception?

Explanation: If both base and derived classes are caught as exceptions then catch block of derived class must appear before the base class. If we put base class first then the derived class catch block will never be reached.

What happens if an exception is thrown outside a catch block?

If a catch block ends normally, without a throw , the flow of control passes over all other catch blocks associated with the try block. Whenever an exception is thrown and caught, and control is returned outside of the function that threw the exception, stack unwinding takes place.

What happens if exception occurs in base class?

If both base and derived classes are caught as exceptions, then the catch block of the derived class must appear before the base class.


3 Answers

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.

like image 90
skypjack Avatar answered Oct 11 '22 15:10

skypjack


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

like image 28
user3684792 Avatar answered Oct 11 '22 15:10

user3684792


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

So checking the derived type first would catch that.

like image 30
Bo Persson Avatar answered Oct 11 '22 15:10

Bo Persson