Menu
Coddy logo textTech

Exception Handling in OOP

Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 81 of 104.

Exception handling in C++ provides a structured way to detect and respond to runtime errors. In object-oriented programming, exceptions integrate naturally with class hierarchies, allowing you to create meaningful error types that carry context about what went wrong.

The basic mechanism uses three keywords: try, throw, and catch. Code that might fail goes in a try block, errors are signaled with throw, and catch blocks handle specific exception types:

#include <iostream>
#include <stdexcept>

class BankAccount {
    double balance;
public:
    BankAccount(double b) : balance(b) {}
    
    void withdraw(double amount) {
        if (amount > balance) {
            throw std::runtime_error("Insufficient funds");
        }
        balance -= amount;
    }
    
    double getBalance() const { return balance; }
};

int main() {
    BankAccount account(100.0);
    
    try {
        account.withdraw(150.0);
    } catch (const std::runtime_error& e) {
        std::cout << "Error: " << e.what() << "\n";
    }
    
    std::cout << "Balance: " << account.getBalance() << "\n";
}

The C++ standard library provides a hierarchy of exception classes rooted at std::exception. Common derived classes include std::runtime_error for runtime issues and std::logic_error for programming mistakes. All standard exceptions provide a what() method that returns an error message.

When an exception is thrown, the stack unwinds - destructors are called for all local objects as the program searches for a matching catch block. This ensures proper cleanup even when errors occur, which is why RAII and exception handling work so well together.

challenge icon

Challenge

Easy

Let's build a safe division calculator that demonstrates exception handling in an object-oriented context. You'll create a Calculator class that performs division operations and throws meaningful exceptions when something goes wrong, then handle those exceptions gracefully in your main program.

You'll organize your code across three files:

  • Calculator.h: Define your Calculator class that performs mathematical operations with proper error handling.

    Your Calculator should have a method divide(double numerator, double denominator) that returns the result of the division. However, if the denominator is zero, it should throw a std::runtime_error with the message Division by zero. If either the numerator or denominator is negative, it should throw a std::invalid_argument with the message Negative values not allowed.

    Also include a method safeSqrt(double value) that returns the square root of the value. If the value is negative, throw a std::runtime_error with the message Cannot compute square root of negative number. You'll need to include <cmath> for the sqrt function.

  • Calculator.cpp: Implement the methods declared in your header file. Make sure to include the necessary headers (<stdexcept> and <cmath>) and check the conditions before performing the operations.
  • main.cpp: Read three inputs (each on a separate line):
    1. Operation type: either divide or sqrt
    2. First number (double)
    3. Second number (double) — only used for division, ignored for sqrt

    Create a Calculator object and perform the requested operation inside a try block. If the operation succeeds, print Result: [value]. If an exception is caught, print Error: [message] where the message comes from the exception's what() method.

    After the try-catch block (regardless of whether an exception occurred), print Calculation complete to demonstrate that the program continues executing after handling exceptions.

For example, with inputs divide, 10, and 2:

Result: 5
Calculation complete

With inputs divide, 10, and 0:

Error: Division by zero
Calculation complete

With inputs divide, -5, and 2:

Error: Negative values not allowed
Calculation complete

With inputs sqrt, 16, and 0:

Result: 4
Calculation complete

With inputs sqrt, -9, and 0:

Error: Cannot compute square root of negative number
Calculation complete

Notice how the program gracefully handles errors by catching exceptions and displaying meaningful messages, then continues execution. This pattern keeps your error handling clean and your main logic focused on the happy path.

Cheat sheet

Exception handling in C++ uses three keywords: try, throw, and catch. Code that might fail goes in a try block, errors are signaled with throw, and catch blocks handle specific exception types:

try {
    // Code that might throw an exception
    account.withdraw(150.0);
} catch (const std::runtime_error& e) {
    std::cout << "Error: " << e.what() << "\n";
}

Throwing exceptions from class methods:

void withdraw(double amount) {
    if (amount > balance) {
        throw std::runtime_error("Insufficient funds");
    }
    balance -= amount;
}

The C++ standard library provides exception classes rooted at std::exception. Common types include:

  • std::runtime_error - for runtime issues
  • std::logic_error - for programming mistakes
  • std::invalid_argument - for invalid arguments

All standard exceptions provide a what() method that returns an error message.

When an exception is thrown, the stack unwinds - destructors are called for all local objects as the program searches for a matching catch block, ensuring proper cleanup.

Include <stdexcept> to use standard exception classes.

Try it yourself

#include <iostream>
#include <string>
#include "Calculator.h"

using namespace std;

int main() {
    // Read inputs
    string operation;
    double num1, num2;
    
    cin >> operation;
    cin >> num1;
    cin >> num2;
    
    // Create Calculator object
    Calculator calc;
    
    // TODO: Use a try-catch block to perform the operation
    // - If operation is "divide", call calc.divide(num1, num2)
    // - If operation is "sqrt", call calc.safeSqrt(num1)
    // - On success, print "Result: " followed by the result
    // - Catch exceptions and print "Error: " followed by the exception message (use what())
    // - After the try-catch, always print "Calculation complete"
    
    
    return 0;
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming