Lesson 18 · 18 of 20
Exceptions: try, catch and throw · C++
Handle errors in C++ with exceptions: throw std::invalid_argument and std::runtime_error, then catch them with try and catch.

When a function cannot do its job, `throw` raises an exception: the function stops right there and the error travels up to whoever called it. withdraw throws std::invalid_argument if the amount is not positive and std::runtime_error if there is not enough money. Both classes live in <stdexcept> and carry a message.
Code that may fail goes inside `try`. If an exception is thrown, the rest of the block is skipped (balance is not updated and Withdrew is not printed) and the first `catch` whose type matches runs instead.
Exceptions are caught by const reference, const std::invalid_argument& e, and `e.what()` returns the message they were thrown with. After the catch, the loop carries on with the next request: one error does not stop the program.
The standard library throws exceptions too: std::stoi("twenty") cannot convert the text and throws std::invalid_argument, and at() out of range throws std::out_of_range. `std::exception` is the base class of them all, so catch (const std::exception&) catches every one. If you do not need the message, you can leave out the name e.
An exception nobody catches ends the program with an error. catch (...), with three dots, catches anything at all.
Code · main.cpp
#include <iostream>#include <stdexcept>#include <string>#include <vector>// throw stops the function and sends an error to whoever called it.double withdraw(double balance, double amount) { if (amount <= 0) throw std::invalid_argument("the amount must be positive"); if (amount > balance) throw std::runtime_error("not enough money"); return balance - amount;}int main() { double balance = 100; std::vector<double> requests = {30, -5, 200, 50}; for (double amount : requests) { try { // try runs the code; the first matching catch handles the error balance = withdraw(balance, amount); std::cout << "Withdrew " << amount << ", balance " << balance << '\n'; } catch (const std::invalid_argument& e) { std::cout << "Invalid request " << amount << ": " << e.what() << '\n'; } catch (const std::runtime_error& e) { std::cout << "Refused " << amount << ": " << e.what() << '\n'; } } // The library throws too: std::stoi with text that is not a number. try { std::cout << std::stoi("twenty") << '\n'; } catch (const std::exception&) { // std::exception catches any standard error std::cout << "\"twenty\" is not a number, but the program goes on\n"; } return 0;}Output · c++ -std=c++17 main.cpp -o main && ./main
Withdrew 30, balance 70 Invalid request -5: the amount must be positive Refused 200: not enough money Withdrew 50, balance 20 "twenty" is not a number, but the program goes on
Key points
throw std::runtime_error("message")raises an error.try { ... }wraps the code that may fail.catch (const Type& e)handles it;e.what()gives the message.- The first
catchwhose type matches is the one that runs. std::exceptioncatches any standard library error.
Exercise
Give withdraw a limit of 60 euros per operation that throws std::out_of_range("over the limit"), add the matching catch in main and test it with a request for 80.