Exception Handling in C++

Introduction

Exception handling in C++ is a mechanism that allows a program to deal with unexpected events or errors that occur during runtime. By using exceptions, you can separate error-handling code from regular code, making the program more readable and maintainable. The core keywords used for exception handling in C++ are try, catch, and throw.

Basic Concepts

  • try block: Contains code that might throw an exception.
  • catch block: Contains code that handles the exception.
  • throw statement: Used to signal the occurrence of an exception.

Syntax

Basic Syntax

try {
    // Code that may throw an exception
} catch (exception_type e) {
    // Code to handle the exception
}

Examples

Example 1: Basic Exception Handling

#include <iostream>
using namespace std;

int main() {
    try {
        int x = 10;
        int y = 0;
        if (y == 0) {
            throw "Division by zero error!";
        }
        int z = x / y;
        cout << z << endl;
    } catch (const char* e) {
        cout << "Caught exception: " << e << endl;
    }

    return 0;
}

Output

Caught exception: Division by zero error!

Explanation

  • The try block contains code that may throw an exception.
  • If y is zero, a throw statement is used to signal a division by zero error.
  • The catch block catches the exception and prints an error message.

Example 2: Multiple Catch Blocks

#include <iostream>
using namespace std;

int main() {
    try {
        throw 20;
    } catch (int e) {
        cout << "Caught an integer exception: " << e << endl;
    } catch (const char* e) {
        cout << "Caught a string exception: " << e << endl;
    }

    try {
        throw "An error occurred";
    } catch (int e) {
        cout << "Caught an integer exception: " << e << endl;
    } catch (const char* e) {
        cout << "Caught a string exception: " << e << endl;
    }

    return 0;
}

Output

Caught an integer exception: 20
Caught a string exception: An error occurred

Explanation

  • The first try block throws an integer exception, which is caught by the first catch block.
  • The second try block throws a string exception, which is caught by the second catch block.

Example 3: Standard Exception Classes

C++ provides a hierarchy of standard exception classes in the <exception> header.

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

int main() {
    try {
        throw runtime_error("Runtime error occurred");
    } catch (const runtime_error& e) {
        cout << "Caught runtime_error: " << e.what() << endl;
    } catch (const exception& e) {
        cout << "Caught exception: " << e.what() << endl;
    }

    return 0;
}

Output

Caught runtime_error: Runtime error occurred

Explanation

  • The try block throws a runtime_error exception.
  • The first catch block catches the runtime_error exception and prints the error message using the what method.
  • The second catch block is a general handler for any other exception types.

Example 4: Custom Exception Classes

You can define your own exception classes by inheriting from std::exception.

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

class MyException : public exception {
public:
    const char* what() const noexcept override {
        return "My custom exception occurred";
    }
};

int main() {
    try {
        throw MyException();
    } catch (const MyException& e) {
        cout << "Caught MyException: " << e.what() << endl;
    }

    return 0;
}

Output

Caught MyException: My custom exception occurred

Explanation

  • The MyException class inherits from std::exception and overrides the what method to return a custom error message.
  • The main function throws a MyException object, which is caught by the catch block and prints the custom error message.

Example 5: Re-throwing Exceptions

You can re-throw an exception using the throw statement without any arguments inside a catch block.

#include <iostream>
using namespace std;

void func() {
    try {
        throw runtime_error("Error in func");
    } catch (...) {
        cout << "Caught exception in func, re-throwing..." << endl;
        throw; // Re-throw the exception
    }
}

int main() {
    try {
        func();
    } catch (const exception& e) {
        cout << "Caught exception in main: " << e.what() << endl;
    }

    return 0;
}

Output

Caught exception in func, re-throwing...
Caught exception in main: Error in func

Explanation

  • The func function throws a runtime_error exception and catches it using a catch block.
  • The catch block in func re-throws the exception using the throw statement.
  • The main function catches the re-thrown exception and prints the error message.

Example 6: Exception Specifications (Deprecated in C++11, Removed in C++17)

Prior to C++11, exception specifications were used to specify which exceptions a function might throw. They are now deprecated and replaced by noexcept.

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

void func() noexcept {
    // This function is specified to not throw exceptions
    cout << "This function does not throw exceptions" << endl;
}

int main() {
    try {
        func();
    } catch (...) {
        cout << "Caught exception" << endl;
    }

    return 0;
}

Output

This function does not throw exceptions

Explanation

  • The func function is declared with noexcept, indicating that it does not throw exceptions.
  • The main function calls func, and no exceptions are thrown or caught.

Conclusion

Exception handling in C++ allows you to manage runtime errors in a controlled and predictable manner. By using try, catch, and throw statements, along with standard and custom exception classes, you can write robust and maintainable code. Understanding and effectively using exception handling is essential for writing reliable C++ programs.

Leave a Comment

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

Scroll to Top