Lección 18 · 18 de 20
Excepciones: try, catch y throw · C++
Gestione errores en C++ con excepciones: lance std::invalid_argument y std::runtime_error con throw y captúrelos con try y catch.

Cuando una función no puede hacer su trabajo, `throw` lanza una excepción: la función se detiene en ese punto y el error sube hasta quien la llamó. withdraw lanza std::invalid_argument si la cantidad no es positiva y std::runtime_error si no hay saldo suficiente. Las dos clases están en <stdexcept> y guardan un mensaje.
El código que puede fallar va dentro de `try`. Si se lanza una excepción, se salta el resto del bloque (ni se actualiza balance ni se escribe Withdrew) y se ejecuta el primer `catch` cuyo tipo coincida.
Las excepciones se capturan por referencia constante, const std::invalid_argument& e, y `e.what()` devuelve el mensaje con el que se lanzaron. Después del catch, el bucle sigue con la siguiente petición: un error no detiene el programa.
La biblioteca estándar también lanza excepciones: std::stoi("twenty") no puede convertir el texto y lanza std::invalid_argument, y at() fuera de rango lanza std::out_of_range. `std::exception` es la clase base de todas, así que catch (const std::exception&) las captura todas. Si no necesita el mensaje, puede omitir el nombre e.
Una excepción que nadie captura termina el programa con un error. catch (...), con tres puntos, captura cualquier cosa.
Código · 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;}Salida · 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
Para recordar
throw std::runtime_error("mensaje")lanza un error.try { ... }encierra el código que puede fallar.catch (const Tipo& e)lo captura;e.what()da el mensaje.- Se ejecuta el primer
catchcuyo tipo coincide. std::exceptioncaptura cualquier error de la biblioteca estándar.
Ejercicio
Añada a withdraw un límite de 60 euros por operación que lance std::out_of_range("over the limit"), y su catch correspondiente en main. Pruébelo con una petición de 80.