exception


Header: : <exception>

The <exception> header is a fundamental part of the C++ Standard Library that provides support for exception handling. It defines the base class for all exceptions (std::exception) and several standard exception classes derived from it. This header is crucial for implementing robust error handling mechanisms in C++ programs, allowing for the separation of error detection and error handling code.

Key Characteristics

Example 1: Basic Exception Handling

#include <exception>
#include <iostream>
#include <stdexcept>

double divide(double numerator, double denominator) {
    if (denominator == 0) {
        throw std::runtime_error("Division by zero!");
    }
    return numerator / denominator;
}

int main() {
    try {
        std::cout << "Result: " << divide(10, 2) << std::endl;
        std::cout << "Result: " << divide(10, 0) << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

Explanation:

Example 2: Custom Exception Class

#include <exception>
#include <string>
#include <iostream>

class CustomException : public std::exception {
private:
    std::string message;

public:
    explicit CustomException(const std::string& msg) : message(msg) {}

    const char* what() const noexcept override {
        return message.c_str();
    }
};

void riskyFunction(int value) {
    if (value < 0) {
        throw CustomException("Negative value not allowed");
    }
    std::cout << "Processing value: " << value << std::endl;
}

int main() {
    try {
        riskyFunction(5);
        riskyFunction(-1);
    } catch (const CustomException& e) {
        std::cerr << "Custom exception caught: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Standard exception caught: " << e.what() << std::endl;
    }

    return 0;
}

Explanation:

Example 3: Nested Exceptions

#include <exception>
#include <stdexcept>
#include <iostream>

void innerFunction() {
    throw std::runtime_error("Inner error");
}

void outerFunction() {
    try {
        innerFunction();
    } catch (const std::exception& e) {
        std::throw_with_nested(std::runtime_error("Outer error"));
    }
}

void printException(const std::exception& e, int level = 0) {
    std::cerr << std::string(level, ' ') << "Exception: " << e.what() << std::endl;
    try {
        std::rethrow_if_nested(e);
    } catch (const std::exception& nested) {
        printException(nested, level + 1);
    }
}

int main() {
    try {
        outerFunction();
    } catch (const std::exception& e) {
        std::cout << "Caught exception. Hierarchy:" << std::endl;
        printException(e);
    }

    return 0;
}

Explanation:

Example 4: Exception Handling with Standard Exceptions

#include <exception>
#include <stdexcept>
#include <iostream>
#include <vector>

void demonstrateExceptions() {
    std::vector<int> vec(5);

    try {
        // Demonstrate out_of_range
        std::cout << vec.at(10) << std::endl;
    } catch (const std::out_of_range& e) {
        std::cerr << "Out of range error: " << e.what() << std::endl;
    }

    try {
        // Demonstrate bad_alloc
        std::vector<int> hugeVector(std::vector<int>::max_size());
    } catch (const std::bad_alloc& e) {
        std::cerr << "Bad allocation error: " << e.what() << std::endl;
    }

    try {
        // Demonstrate invalid_argument
        std::stoi("not a number");
    } catch (const std::invalid_argument& e) {
        std::cerr << "Invalid argument error: " << e.what() << std::endl;
    }
}

int main() {
    try {
        demonstrateExceptions();
    } catch (const std::exception& e) {
        std::cerr << "Caught unhandled exception: " << e.what() << std::endl;
    }

    return 0;
}

Explanation:

Additional Considerations

  1. Exception Safety: Ensure resources are properly managed when exceptions occur (e.g., using RAII).

  2. Performance: Exception handling can have a performance cost, especially in tight loops.

  3. Noexcept Specifier: Use noexcept for functions that don't throw exceptions to enable compiler optimizations.

  4. Exception Specifications: Modern C++ discourages the use of dynamic exception specifications.

  5. Catch by Reference: Always catch exceptions by reference to avoid slicing.

Summary

The <exception> header in C++ provides essential tools for exception handling:

Exception handling is a powerful mechanism for managing errors and exceptional conditions in C++ programs. It allows for the separation of error detection and error handling code, leading to cleaner and more robust software. By using the facilities provided by <exception>, developers can create more resilient applications that gracefully handle unexpected situations and provide meaningful error information to users or logging systems.

When using exceptions, it's important to consider exception safety, performance implications, and to design exception hierarchies that make sense for your application's error handling needs. Proper use of exceptions can significantly improve the reliability and maintainability of C++ code.

Related

Previous Page | Course Schedule | Course Content