EZ

Eduzan

Learning Hub

Eduzan
Eduzan / C++

Exception Handling

In C++, exceptions are unexpected events or errors that occur during the execution of a program. When such an event occurs, the program flow is interrupted, and if the exception is not handled, it can cause the program to terminate abnormally. Exception handling provides a way to manage these runtime anomalies and keep the program running by transferring control from one part of the code to another where the exception can be dealt with.

What is a C++ Exception?

An exception is a problem that arises during the execution of a program, leading to an abnormal termination if not handled. Exceptions occur at runtime, meaning the problem is only encountered when the program is running.

Types of Exceptions in C++

In C++, exceptions can be categorized into two types:

1. Synchronous Exceptions: These occur due to errors like dividing by zero, invalid input, or logic errors that can be anticipated by the programmer.
2. Asynchronous Exceptions: These are exceptions caused by external events beyond the program’s control, such as hardware failure, system interrupts, etc.

Exception Handling Mechanism in C++

C++ provides a built-in mechanism for exception handling through three main keywords: trycatch, and throw.

Syntax of try-catch in C++:

try {
    // Code that might throw an exception
    throw SomeExceptionType("Error message");
}
catch( ExceptionType e ) {
    // Code to handle the exception
}

1. Separation of Error–Handling Code from Normal Code: Unlike traditional methods where error-checking code is mixed with normal logic, exceptions keep the code cleaner and more readable.
2. Granular Handling: A function can throw many exceptions but choose to handle only specific ones. The rest can be caught by the calling function.
3. Grouping Error Types: C++ allows you to group exceptions into classes and objects, making it easier to categorize and manage different error types.

Example 1: Basic try-catch Mechanism

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

int main() {
    try {
        int numerator = 10;
        int denominator = 0;
        int result;

        if (denominator == 0) {
            throw runtime_error("Division by zero is not allowed.");
        }

        result = numerator / denominator;
        cout << "Result: " << result << endl;
    }
    catch (const exception& e) {
        cout << "Exception caught: " << e.what() << endl;
    }

    return 0;
}

Output:

Exception caught: Division by zero is not allowed.

In this example, dividing by zero throws a runtime_error exception, which is caught by the catch block.

Example 2: Throwing and Catching Exceptions

#include <iostream>
using namespace std;

int main() {
    int value = -1;

    cout << "Before try block" << endl;

    try {
        cout << "Inside try block" << endl;
        if (value < 0) {
            throw value;
        }
        cout << "After throw (will not be executed)" << endl;
    }
    catch (int ex) {
        cout << "Caught an exception: " << ex << endl;
    }

    cout << "After catch block" << endl;
    return 0;
}

Output:

Before try block
Inside try block
Caught an exception: -1
After catch block

Here, a negative value throws an exception, and control transfers to the catch block, where the exception is handled.

Properties of Exception Handling in C++

Property 1: Catch-All Block : –C++ provides a catch-all mechanism to catch exceptions of any type using catch(...).

#include <iostream>
using namespace std;

int main() {
    try {
        throw 10; // Throwing an integer
    }
    catch (char*) {
        cout << "Caught a char exception." << endl;
    }
    catch (...) {
        cout << "Caught a default exception." << endl;
    }
    return 0;
}

Output:

Caught a default exception.

Property 2: Uncaught Exceptions Terminate the Program :- If an exception is not caught anywhere in the code, the program terminates abnormally.

#include <iostream>
using namespace std;

int main() {
    try {
        throw 'x'; // Throwing a char
    }
    catch (int) {
        cout << "Caught int" << endl;
    }
    return 0;
}

Output:

terminate called after throwing an instance of 'char'

Property 3: Unchecked Exceptions :- C++ does not enforce checking for exceptions at compile time. However, it is recommended to list possible exceptions.

#include <iostream>
using namespace std;

void myFunction(int* ptr, int x) throw(int*, int) {
    if (ptr == nullptr) throw ptr;
    if (x == 0) throw x;
}

int main() {
    try {
        myFunction(nullptr, 0);
    }
    catch (...) {
        cout << "Caught exception from myFunction" << endl;
    }
    return 0;
}

Output:

Caught exception from myFunction
End of lesson.