Loading...
C++ Exception Handling

C++ Exception Handling

In this tutorial, we will learn about Excaption Handling in C++ with the help of examples.

Exception Handling

One of the advantages of C++ over C is Exception Handling. Exception Handling in C++ is a process to handle runtime errors. We perform exception handling so the normal flow of the application can be maintained even after runtime errors.
In C++, exception is an event or object which is thrown at runtime. All exceptions are derived from std::exception class. It is a runtime error which can be handled. If we don't handle the exception, it prints exception message and terminates the program

There are two types of exceptions:
a) Synchronous
b) Asynchronous (Ex:which are beyond the program’s control, Disc failure etc).


Exception Handling Keywords

C++ provides following specialized keywords for this purpose:
1. throw- Used to throw an exception. Also used to list the exceptions that a function throws, but doesn’t handle itself.
2. catch- represents a block of code that is executed when a particular exception is thrown.
3. try- represents a block of code that can throw an exception.


Why Exception Handling?

Following are main advantages of exception handling over traditional error handling.
1. You will separate your error handling code from your normal code. The code will be more readable and easier to maintain.
2. Functions can handle the exceptions they choose. Even if a function throws many exceptions, it will only handle some. The caller will handle the uncaught exceptions.
3. Grouping of Error Types: In C++, both basic types and objects can be thrown as exception. We can create a hierarchy of exception objects, group exceptions in namespaces or classes, categorize them according to types.


Syntax

The try/catch takes this syntax:

try {
   // the protected code
} catch( Exception_Name exception1 ) {
   // catch block
} catch( Exception_Name exception2 ) {
   // catch block
} catch( Exception_Name exceptionN ) {
   // catch block
}
  • Although we have one try statement, we can have many catch statements.
  • The ExceptionName is the name of the exception to be caught.
  • The exception1, exception2, and exceptionN are your defined names for referring to the exceptions.

C++ Standard Exceptions

There are some standard exceptions in C++ under which we can use in our programs. They are arranged in a parent-child class hierarchy which is depicted below:

  • std::exception - Parent class of all the standard C++ exceptions.
  • logic_error - Exception happens in the internal logical of a program.
    • domain_error - Exception due to use of invalid domain.
    • invalid argument - Exception due to invalid argument.
    • out_of_range - Exception due to out of range i.e. size requirement exceeds allocation.
    • length_error - Exception due to length error.
  • runtime_error - Exception happens during runtime.
    • range_error - Exception due to range errors in internal computations.
    • overflow_error - Exception due to arithmetic overflow errors.
    • underflow_error - Exception due to arithmetic underflow errors
  • bad_alloc - Exception happens when memory allocation with new() fails.
  • bad_cast - Exception happens when dynamic cast fails.
  • bad_exception - Exception is specially designed to be listed in the dynamic-exception-specifier.
  • bad_typeid - Exception thrown by typeid.

Example 1: C++ Program to demonstrate Exception Handling.

// program explains flow of execution of try/catch blocks.

#include <iostream>
using namespace std;

int main()
{
    int x = -1;
    
    cout << "Before try \n";
    
    try {
        cout << "Inside try \n";
        if (x < 0) {
            throw x;
            cout << "After throw (Never executed) \n";
        }
    }
        catch (int x) {
            cout << "Exception Caught \n";
        }
        cout << "After Caught (Will be executed) \n";
    return 0;
}

Output

Before try
Inside try
Exception Caught
After catch (Will be executed)

Example 2: C++ Program to demonstrate Exception Handling.

There is a special catch block called ‘catch all’ catch(…) that can be used to catch all types of exceptions. For example, in the following program, an int is thrown as an exception, but there is no catch block for int, so catch(…) block will be executed.

#include <iostream>
using namespace std;
int main(){
   
    try {
        throw 10;
    }
    
    catch (char *excp) {
        cout << "Caught " << excp;
    }
    catch (...) {
        cout << "Default Exception \n";
    }
    return 0;
}

Output

Default Exception

Example 3: C++ Program to demonstrate Exception Handling

Implicit type conversion doesn’t happen for primitive types. For example, in the following program ‘a’ is not implicitly converted to int

#include <iostream>
using namespace std;
int main(){
   
    try {
        throw 'a';
    }
    
    catch (int x) {
        cout << "Caught " << x;
    }
    catch (...) {
        cout << "Default Exception \n";
    }
    return 0;
}

Output

Default Exception

Example 4: C++ Program to demonstrate Exception Handling

If an exception is thrown and not caught anywhere, the program terminates abnormally. For example, in the following program, a char is thrown, but there is no catch block to catch a char.

#include <iostream>
using namespace std;
int main(){
   
    try {
        throw 'a';
    }
    
    catch (int x) {
        cout << "Caught " << x;
    }
    return 0;
}

Output

terminate called after throwing an instance of 'char'

This application has requested the Runtime to terminate it in an 
unusual way. Please contact the application's support team for 
more information.

Example 5: C++ Program to demonstrate Exception Handling

Unlike Java, in C++, all exceptions are unchecked. Compiler doesn’t check whether an exception is caught or not (See this for details). For example, in C++, it is not necessary to specify all uncaught exceptions in a function declaration. Although it’s a recommended practice to do so. For example, the following program compiles fine, but ideally signature of fun() should list unchecked exceptions.

#include <iostream>
using namespace std;
// Here we specify the exceptions that this function throws.
void fun(int *ptr, int x) throw(int *, int){
   
    if (ptr == NULL) {
        throw ptr;
    }
    if (x == 0) {
        throw x;
        // some functionality.
    }
}
int main(){
   
    try {
        fun(NULL, 0);
    }
    
    catch (...) {
        cout << "Caught exception from fun()";
    }
    return 0;
}

Output

Caught exception from fun()

Example 6: C++ Program to demonstrate Exception Handling

Unlike Java, in C++, all exceptions are unchecked. Compiler doesn’t check whether an exception is caught or not (See this for details). For example, in C++, it is not necessary to specify all uncaught exceptions in a function declaration. Although it’s a recommended practice to do so. For example, the following program compiles fine, but ideally signature of fun() should list unchecked exceptions.

#include <iostream>
using namespace std;
Class Exam{
    public:
    Exam() {cout << "Constructor of Exam \n"; }
    ~ Exam() {cout << "Destructor of Exam \n"; }
};
int main(){
   
    try {
        Exam e1;
        throw 10;
    }
    catch (int i) {
        cout << "Caught " << i << endl;
    }
    return 0;
}

Output

Constructor of Test
Destructor of Test
Caught 10

Example 7: C++ Program to demonstrate Exception Handling

When an exception is thrown, all objects created inside the enclosing try block are destructed before the control is transferred to catch block.

#include <iostream>
using namespace std;
int main(){
   
    try {
        try {
            throw 20;
        }
        catch (int n) {
            cout << "Handle Partially ";
            throw; // Re-throwing an exception

        }
    }
    
    catch (int n) {
        cout << "Handle remaining ";
    }
    return 0;
}

Output

Handle Partially Handle remaining

User-Defined Exceptions

The C++ std::exception class allows us to define objects that can be thrown as exceptions. This class has been defined in the header. The class provides us with a virtual member function named what.

This function returns a null-terminated character sequence of type char *. We can overwrite it in derived classes to have an exception description.


Example 8: C++ Program to demonstrate User-Defined Exceptions

#include <iostream>
#include <exception>
using namespace std;

Class Excep : public exception{

    Virtual const char* what() const throw()
    {
        return "Excep Occurred";
    }
} newex;
int main(){
   
    try {
        throw newex;
    }
    catch (exception ex) {
        cout << ex.what() << endl;
    }
    return 0;
}

Output

Excep Occurred

Advantage

It maintains the normal flow of the application. In such case, rest of the code is executed even after exception.


Next Tutorial

We hope that this tutorial helped you develop better understanding of the concept of Exception Handling in C++.

Keep Learning : )

In the next tutorial, you'll learn about C++ Multithreading.

- Related Topics