C++ Exception handling

Manage errors in C++.

* Exception handling is a powerful feature that allows you to write more robust and maintainable code by separating error-handling code from the main logic.

Exception handling

Exception handling in C++ allows you to gracefully manage errors and unexpected situations in your code. It involves throwing and catching exceptions to handle abnormal conditions. Here's a brief overview of how exception handling works in C++:

1. Throwing Exceptions:

You can throw an exception using the 'throw' keyword. Typically, this is done when an error or unexpected condition occurs in your code.

if (/* some condition */) {
        throw std::runtime_error("Something went wrong!");
    }

2. Catching Exceptions:

To catch exceptions, you use a 'try' block. The 'catch' block specifies the type of exception to catch and the code to execute when that exception is thrown.

try {
        // Code that may throw an exception
        someFunction();
    } catch (const std::runtime_error& e) {
        // Handle the exception
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }

3. Exception Hierarchies:

C++ supports a hierarchy of exception types. You can catch a more general exception type to catch all its derived types.

try {
    // Code that may throw an exception
} catch (const std::exception& e) {
    // Handle the exception
    std::cerr << "Exception caught: " << e.what() << std::endl;
}

4. Custom Exceptions:

Define your own exception classes by deriving from 'std::exception' or its subclasses.

class CustomException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Custom Exception";
    }
};

void someFunction() {
    // ...
    if (/* some condition */) {
        throw CustomException();
    }
    // ...
}

5. Cleanup with finally (using RAII):

Resource management is often handled using Resource Acquisition Is Initialization (RAII). Objects acquire resources in their constructors and release them in their destructors.

cpp Copy Code
#include<iostream>
#include<fstream>

class FileHandler {
public:
    FileHandler(const char* filename) : file(filename) {
        if (!file.is_open()) {
            throw std::runtime_error("Failed to open file");
        }
    }

    // Destructor releases the resource
    ~FileHandler() {
        file.close();
    }

private:
    std::ofstream file;
};

int main() {
    try {
        FileHandler file("example.txt");
        // Code that may throw an exception
        std::cout << "No error was found." << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}
Output:
No error found.

6. Noexcept:

The 'noexcept' specifier is used to indicate whether a function might throw exceptions. It is especially useful for optimizing code and for expressing the intent of not throwing exceptions.

void myFunction() noexcept {
    // This function will not throw exceptions
    // ...
}

Exception handling provides a flexible and powerful mechanism for dealing with errors, but it should be used judiciously. Overusing exceptions for control flow can make code harder to read and maintain. Always consider alternatives and choose the right tool for the job.

What's Next?

We actively create content for our YouTube channel and consistently upload or share knowledge on the web platform.