Home C++ Introduction Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Recursion Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess STL Modern C++ Misc Books ----


Exceptions


Contents

Custom Exception

We can also throw an object of our own class.
File: except6.cpp
#include <iostream>
#include <fstream>

using namespace std;

class MyException 
{ 
 public:    
  string messg ;  
  MyException( string str1 )
   { 
    messg = str1 ; 
   }
};

int main()
{  
 try 
  {   
    throw MyException("Error") ; 
  } 
 catch ( MyException& e1 ) 
  { 
    cout << e1.messg   << endl ; 
  }  
 return 0;
 
}
$ g++ except6.cpp ; ./a.exe
Error

Notice we have been using the reference in the catch statement

catch ( MyException& e1 )

The below program shows the difference between using regular objects
instead of references.



File: scope1.cpp
#include <iostream>
#include <fstream>

using namespace std;

class MyException
{
 public:
  string messg ;
  MyException( string str1 )
   {
     messg = str1 ;
     cout << "MyException: constructor: " << messg << endl ;
   }

  MyException( const MyException& obj1 )
   {
     messg = obj1.messg  ;
     cout << "MyException: copy constructor: " << messg << endl ;
   }

   ~MyException(  )
    {
      cout << "MyException: destructor: " << messg << endl ;
    }
};

int main()
{
     try
      {
        MyException  error1("Error 1:")  ;
        throw MyException("Error 2:") ;
      }
     catch ( MyException error2 )
      {
        cout << error2.messg   << endl ;
      }
    cout << "Step 1:" << endl ;

    try
     {
             throw MyException("Error 3:") ;
     }
    catch(  MyException& error3 )
     {
        cout << error3.messg   << endl ;
     }

  cout << "Step 2:" << endl ;

 return 0;

}

$ g++ scope1.cpp ; ./a.exe
MyException: constructor: Error 1:
MyException: constructor: Error 2:
MyException: destructor: Error 1:
MyException: copy constructor: Error 2:
Error 2:
MyException: destructor: Error 2:
MyException: destructor: Error 2:
Step 1:
MyException: constructor: Error 3:
Error 3:
MyException: destructor: Error 3:
Step 2:


The lines get executed first.

	 try
	  {
		MyException  error1("Error 1:")  ;
		throw MyException("Error 2:") ;
	  }
	 catch ( MyException error2 )
	  {
		cout << error2.messg   << endl ;
	  }

MyException  error1("Error 1:")  ;
This creates the "error1" object and the statement:

MyException: constructor: Error 1:

Then we hit the "throw" statement:

throw MyException("Error 2:") ;

This will create an object and we get the below statement
printed out:

MyException: constructor: Error 2:

We come to the handler but before doing that we need to clean up the local
objects in the "try" block and the destructor for "error1" object get called.

	 catch ( MyException error2 )
	  {
		cout << error2.messg   << endl ;
	  }

The object with the message "Error 2" from the try block
is copied to "error2" object.

MyException: copy constructor: Error 2:

We print out the message "Error 2:"  and the come out of the handler.
This causes the cleanup of the 2 "Error 2" objects: one that was thrown and
the other one that was in the argument to the catch handler.

We print out a debug statement and then hit the lines:

    try
     {
     		throw MyException("Error 3:") ;
	 }
	catch(  MyException& error3 )
	 {
		cout << error3.messg   << endl ;
	 }


Step 1:
MyException: constructor: Error 3:
Error 3:
MyException: destructor: Error 3:
Step 2:

We create the "Error 3:" object in the "try" block and then
jump to the handler. Since the argument "error3" is a reference we do
not create another object and only 1 constructor is called as shown in the output.