techmore.in

C++ Exceptions

In C++, exceptions are a mechanism used to handle errors and other exceptional conditions that may occur during the execution of a program. The exception handling mechanism helps to manage and respond to runtime errors in a controlled way, ensuring that errors are handled gracefully and resources are cleaned up properly.

Key Concepts of Exception Handling

  1. Throwing Exceptions: An exception is thrown when an error condition is detected. This is done using the throw keyword.

  2. Catching Exceptions: The thrown exception is caught using a try block and catch blocks. The try block contains code that might throw an exception, while the catch blocks handle specific types of exceptions.

  3. Exception Propagation: If an exception is not caught by the try block, it propagates up the call stack to the nearest enclosing try block that can handle it.

  4. Finally Block: C++ does not have a finally block like some other languages (e.g., Java), but the cleanup code is often placed in the catch block or using RAII (Resource Acquisition Is Initialization) principles.

Basic Syntax

Throwing an Exception

To throw an exception, use the throw keyword followed by an exception object:

cpp
throw SomeException();

Catching an Exception

Exceptions are caught using try and catch blocks:

cpp
try { // Code that might throw an exception } catch (const SomeException& e) { // Code to handle the exception } catch (...) { // Code to handle any exception }

Example

cpp
#include #include // For std::runtime_error void mightGoWrong() { bool errorOccurred = true; // Simulate an error condition if (errorOccurred) { throw std::runtime_error("Something went wrong!"); } } int main() { try { mightGoWrong(); } catch (const std::runtime_error& e) { std::cout << "Caught an exception: " << e.what() << std::endl; } catch (...) { std::cout << "Caught an unknown exception" << std::endl; } return 0; }

Custom Exceptions

You can define your own exception classes by inheriting from std::exception or one of its derived classes.

Defining a Custom Exception

cpp
#include #include #include class MyException : public std::exception { private: std::string message; public: MyException(const std::string& msg) : message(msg) {} virtual const char* what() const noexcept override { return message.c_str(); } }; void mayThrowCustomException() { throw MyException("This is a custom exception!"); } int main() { try { mayThrowCustomException(); } catch (const MyException& e) { std::cout << "Caught custom exception: " << e.what() << std::endl; } return 0; }

Exception Safety

When writing code that might throw exceptions, you should ensure exception safety. This means making sure that your code handles exceptions without leaving the program in an inconsistent state.

Types of Exception Safety

  1. Basic Guarantee: The program remains in a valid state if an exception is thrown.
  2. Strong Guarantee: If an exception is thrown, the program state is not changed (rollback to the initial state).
  3. No-throw Guarantee: The function guarantees not to throw any exceptions.

RAII (Resource Acquisition Is Initialization)

RAII is a technique used in C++ to manage resources, such as memory or file handles. It ensures that resources are properly released when objects go out of scope, which helps with exception safety.

Example of RAII

cpp
#include #include class FileWrapper { private: std::ofstream file; public: FileWrapper(const std::string& filename) : file(filename) { if (!file) { throw std::runtime_error("Failed to open file"); } } ~FileWrapper() { if (file.is_open()) { file.close(); } } void write(const std::string& data) { file << data; } }; int main() { try { FileWrapper fw("example.txt"); fw.write("Hello, World!"); } catch (const std::exception& e) { std::cout << "Exception: " << e.what() << std::endl; } return 0; }

Best Practices

  1. Use Standard Exceptions: Prefer using standard exception classes (e.g., std::runtime_error, std::out_of_range) when possible.
  2. Catch by Reference: Catch exceptions by reference to avoid slicing and unnecessary copying.
  3. Handle Exceptions at Appropriate Levels: Handle exceptions at levels where you can meaningfully recover or log the issue.
  4. Avoid Exceptions for Control Flow: Use exceptions for exceptional conditions, not for regular control flow.