Fundamentals 8 min read

Mastering C++ Exception Handling: Throw, Try, and Catch Explained

Learn how C++ exception handling separates error management from normal logic using the throw, try, and catch keywords, covering best practices, stack unwinding, performance considerations, and comprehensive code examples that demonstrate throwing standard exceptions, catching specific types, and handling unknown errors.

php Courses
php Courses
php Courses
Mastering C++ Exception Handling: Throw, Try, and Catch Explained

When writing programs we must handle inevitable, unexpected errors. Traditional error‑code returns mix normal logic with error handling, reducing readability. C++ exception handling separates these concerns, making code more robust and clear.

The mechanism is built around three core keywords: try, catch, and throw.

1. throw : Throw an exception

When a function detects an unrecoverable error it can throw an exception to signal that a problem has occurred.

You can throw any expression type: an int, a string, a custom object, etc.

Best practice is to throw objects derived from std::exception, such as std::runtime_error or std::out_of_range, for clearer, uniform error information.

#include <stdexcept>

double divide(int numerator, int denominator) {
    if (denominator == 0) {
        // Good habit: throw a standard exception
        throw std::runtime_error("Division by zero condition!");
        // You could also throw other types (not recommended in production):
        // throw "Division by zero!"; // string
        // throw -1; // error code
    }
    return static_cast<double>(numerator) / denominator;
}

2. try : Attempt to catch exceptions

The try keyword defines a protected block of code. Any code that may throw an exception is placed inside the try block. If an exception is thrown, control immediately jumps to the matching catch block.

try {
    // Code that may throw
    // Example: call divide(5, 0);
}

3. catch : Capture and handle exceptions

The catch keyword follows a try block and defines an exception handler. Each catch handles a specific exception type; multiple catch blocks can be used for different types.

When an exception is thrown, the program unwinds the stack, skipping the rest of the try block and testing each catch in order until a matching type is found.

Syntax:

catch (ExceptionType [exception_variable]) { /* handling code */ }

ExceptionType: The type to catch, e.g., std::exception&, int, const char*.

exception_variable: Optional variable to access the caught object, usually a (const) reference to avoid copying.

catch (const std::runtime_error& e) {
    std::cerr << "Exception caught: " << e.what();
}
catch (const char* msg) {
    std::cerr << "Exception caught: " << msg << std::endl;
}
catch (...) {
    std::cerr << "Some unknown exception was caught!" << std::endl;
}

Complete workflow and example

The full flow is: try → (exception occurs) → throw → match catch → handle.

#include <iostream>
#include <stdexcept>

double divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("Math error: Attempted to divide by Zero
");
    }
    return static_cast<double>(a) / b;
}

int main() {
    int x = 10;
    int y = 0;
    double result = 0.0;
    try {
        std::cout << "Dividing " << x << " by " << y << std::endl;
        result = divide(x, y);
        std::cout << "The result is " << result << std::endl;
    }
    catch (const std::runtime_error& e) {
        std::cerr << "Exception caught: " << e.what();
    }
    catch (const char* msg) {
        std::cerr << "Exception caught: " << msg << std::endl;
    }
    catch (...) {
        std::cerr << "Some unknown exception was caught!" << std::endl;
    }
    std::cout << "Program continues after the try-catch block." << std::endl;
    return 0;
}

Key Features and Considerations

Stack Unwinding: When an exception is thrown, the runtime walks back up the call stack until a matching catch is found, destroying local objects along the way to avoid resource leaks.

Catch‑All: catch (...) captures any exception type but should be used sparingly, typically for logging or cleanup before re‑throwing.

Exceptions in Destructors: Destructors should not throw. If a destructor throws during stack unwinding, the program usually terminates.

Performance: No overhead when no exception occurs (zero‑cost principle). Overhead appears only when throwing and catching, which is acceptable for error paths.

Conclusion

Using try, catch, and throw dramatically improves C++ error handling and code quality. Follow the “throw by value, catch by reference” rule and prefer the standard exception hierarchy to convey rich error information.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Cerror-managementThrowtrycatch
php Courses
Written by

php Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.