8. How do you handle exceptions in C++?

Basic

8. How do you handle exceptions in C++?

Overview

Exception handling in C++ is a powerful mechanism that allows a program to deal with unexpected situations or errors in a controlled manner. It is crucial for writing robust and error-resistant software, as it helps to separate error-handing code from the normal flow of the program, making it easier to understand, maintain, and debug.

Key Concepts

  1. Try, Catch, and Throw: The fundamental keywords used for exception handling.
  2. Standard Exception Class: The hierarchy of exception classes derived from std::exception.
  3. Resource Management: Using RAII (Resource Acquisition Is Initialization) for managing resources in the presence of exceptions.

Common Interview Questions

Basic Level

  1. How is exception handling implemented in C++?
  2. Write a simple C++ program that demonstrates the use of try, catch, and throw.

Intermediate Level

  1. How do you handle multiple exceptions in C++?

Advanced Level

  1. Discuss exception safety levels in C++ and how you would achieve them in your code.

Detailed Answers

1. How is exception handling implemented in C++?

Answer: Exception handling in C++ is implemented using three keywords: try, catch, and throw. The try block contains code that might throw an exception, the throw keyword is used to throw an exception, and the catch block is used to handle the exception. If an exception is thrown and not caught within the same function, it propagates (is passed on) to the function that called this function. If no catch block catches the exception, the program terminates.

Key Points:
- try blocks contain code that might throw exceptions.
- throw is used to throw an exception.
- catch blocks are used to handle exceptions.

Example:

#include <iostream>

void mightGoWrong() {
    bool errorOccurred = true; // Simulate an error
    if (errorOccurred) {
        throw "Something went wrong!";
    }
}

int main() {
    try {
        mightGoWrong();
    } catch (const char* e) {
        std::cout << "Error caught: " << e << std::endl;
    }

    return 0;
}

2. Write a simple C++ program that demonstrates the use of try, catch, and throw.

Answer: Below is a simple C++ program that demonstrates basic exception handling using try, catch, and throw.

Key Points:
- A function throws an exception using the throw keyword.
- The main function has a try block to execute code that might throw an exception.
- The catch block catches and handles the exception.

Example:

#include <iostream>

void divide(double numerator, double denominator) {
    if (denominator == 0) {
        throw "Division by zero error!";
    }
    std::cout << "Result: " << (numerator / denominator) << std::endl;
}

int main() {
    try {
        divide(10.0, 0.0);
    } catch (const char* errorMsg) {
        std::cout << "Caught an exception: " << errorMsg << std::endl;
    }

    return 0;
}

3. How do you handle multiple exceptions in C++?

Answer: In C++, multiple exceptions can be handled by having multiple catch blocks following a try block. Each catch block is designed to handle a specific type of exception, allowing for different types of errors to be handled in different ways. It's important to order the catch blocks correctly, from the most derived exception classes to the least derived (i.e., most specific to most general).

Key Points:
- Use multiple catch blocks to handle different types of exceptions.
- Order catch blocks from most specific to most general exception types.
- Catching std::exception can serve as a catch-all for standard exceptions.

Example:

#include <iostream>
#include <stdexcept> // For std::runtime_error

void riskyFunction(int a) {
    if (a == 0) {
        throw std::runtime_error("Runtime error occurred");
    } else if (a == 1) {
        throw "C-style string exception";
    }
}

int main() {
    try {
        riskyFunction(0); // Change the argument to test different exceptions
    } catch (const std::runtime_error& e) {
        std::cout << "Standard exception caught: " << e.what() << std::endl;
    } catch (const char* msg) {
        std::cout << "C-style string exception caught: " << msg << std::endl;
    } catch (...) {
        std::cout << "Catch-all handler for any other exceptions" << std::endl;
    }

    return 0;
}

4. Discuss exception safety levels in C++ and how you would achieve them in your code.

Answer: Exception safety in C++ can be categorized into four levels: Nothrow, Strong, Basic, and No guarantee. Achieving these guarantees involves careful design to manage object states and resources across exceptions.

Key Points:
- Nothrow Guarantee: The operation guarantees not to throw any exceptions. This is often achieved using noexcept specifier or by ensuring the operation cannot fail.
- Strong Guarantee: The operation can fail and throw exceptions, but it guarantees that the program state remains unchanged if it does. This often involves transaction-like behavior where changes are only committed if the operation succeeds.
- Basic Guarantee: The operation guarantees that if an exception is thrown, all invariants are preserved and there are no resource leaks. However, the program state may change.
- No Guarantee: No safety guarantees are provided. Throwing an exception could leave the program in an inconsistent state or cause resource leaks.

Example:
To provide a strong guarantee, you might use copy-and-swap idiom for assignment operators:

#include <algorithm> // std::swap

class MyClass {
private:
    int* data;
public:
    MyClass(int value) : data(new int(value)) {}
    ~MyClass() { delete data; }

    // Copy-and-swap idiom for strong exception safety
    MyClass& operator=(MyClass other) {
        std::swap(data, other.data);
        return *this;
    }

    // Copy constructor for deep copy
    MyClass(const MyClass& other) : data(new int(*other.data)) {}
};

In this example, the assignment operator uses the copy-and-swap idiom, which provides a strong exception guarantee. If copying other.data throws, the current object remains untouched, thus preserving program state.