Catch an exception with reference-parameter

Share the Article

When an object is thrown as exception then catch block should have its parameter declared by reference and not by value. In that way the same object will be assigned to reference variable.

#include <iostream> //main header using namespace std;//for namespace class MainFunda { public: MainFunda(){ cout << "MainFunda()" << endl; } A(const MainFunda& rhs) { cout << "MainFunda(copy constructor)" << endl; } ~MainFunda() { cout << "~MainFunda()" << endl; } }; int main() { try { cout << "Starting try block" << endl; throw MainFunda(); cout << "Ending try block" << endl; } catch (MainFunda& a) { cout << "Exception caught in catch(MainFunda&) : " << endl; } return 0; }

The output:

Starting try block MainFunda() Exception caught in catch(MainFunda&) : ~MainFunda()

However, it is still possible to catch the exception by value, but there are 2 main problems in this approach

catch (MainFunda a) //catch by value { cout << "Exception caught in catch(MainFunda) : " << endl; }

Copy Construction: First problem is that the constructor creates a new duplicate copy of thrown object. This parameter variable gets the copy and not original exception. The compiler invokes copy constructor to create this duplicate copy object

The compiler produces following output with such catch block:

Starting try block MainFunda() MainFunda(copy constructor) Exception caught in catch(MainFunda) : ~MainFunda() ~MainFunda()

Object Slicing: Second, problem happens in case of inheritance. This is a scenario, when the argument is of type base class and exception is of type derived object. Here, compiler will slice the Derived class object. The exception object is initially of type Derived class but when it reaches inside the catch block it will become a Base object due to such slicing.

#include <iostream> //main header using namespace std; //for namespace class MFBase { public: virtual void printtype() { cout << "Base Object" << endl; } }; class MFDerived : public MFBase { public: virtual void printtype() { cout << "Derived Object" << endl; } }; int main() { try { cout << "Starting try block" << endl; throw MFDerived(); cout << "Ending try block" << endl; } catch (MFBase b) //MFBase type, catch by value { cout << "Exception caught" << endl; b.printtype(); } return 0; }

The output is as follows:

Starting try block Exception caught Base Object

The correct way to specify catch in this example is by reference:

catch (MFBase& b)//Base type parameter, catch by reference { cout << "Exception caught" << endl; b.printtype(); }

The output will be as follows:

Starting try block Exception caught Derived Object

When multiple catch blocks match the type of exception thrown

In such case, the compiler will call the first catch block which matches the exception, and it ignores all the other catch blocks. The compiler will ignore the other catch blocks even if they are compatible. However, compiler shall generate warnings in such cases.

#include <iostream> //main header using namespace std;//for namespace class MFBase { public: virtual void printtype() {cout << "Base" << endl; } }; class MFDerived : public MFBase { public: virtual void printtype() {cout << "Derived Object" << endl; } }; int main() { try { cout << "Starting try block" << endl; throw MFDerived(); cout << "Ending try block" << endl; } catch (MFBase& b) { cout << "Exception caught : MFBase&" << endl; b.printtype(); } catch (MFDerived& b) { cout << "Exception caught : MFDerived&" << endl; b.printtype(); } return 0; }

The output is:

compiler warning when an exception  is caught by a handler which occurs earlier than a more suitable

Main Funda: The exception object must always be caught by reference otherwise it creates problems

Related Topics:

Why a destructor should never throw exception?
What is the problem with setjmp( ) & longjmp( ) ?
Basics of throwing and catching exception
What happens when exception thrown from a constructor?
Re-throwing an exception
What are function level try-catch blocks
Understanding exception specification for functions
Explaining C++ casts
How pointer to class members are different ?
What is reference collapsing?
How to make a class object un-copyable?

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *