Menu
Coddy logo textTech

Manejo de excepciones en POO

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 81 de 104.

El manejo de excepciones en C++ proporciona una forma estructurada de detectar y responder a los errores en tiempo de ejecución. En la programación orientada a objetos, las excepciones se integran de forma natural con las jerarquías de clases, lo que te permite crear tipos de error significativos que incluyen contexto sobre lo que salió mal.

El mecanismo básico utiliza tres palabras clave: try, throw y catch. El código que podría fallar se coloca en un bloque try, los errores se señalan con throw y los bloques catch gestionan tipos específicos de excepciones:

#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";
}

La biblioteca estándar de C++ proporciona una jerarquía de clases de excepciones cuyo origen es std::exception. Entre las clases derivadas comunes se incluyen std::runtime_error para problemas durante la ejecución y std::logic_error para errores de programación. Todas las excepciones estándar proporcionan un método what() que devuelve un mensaje de error.

Cuando se lanza una excepción, la pila se desenrolla: se llaman a los destructores de todos los objetos locales mientras el programa busca un bloque catch coincidente. Esto garantiza una limpieza adecuada incluso cuando se producen errores, por lo que RAII y el manejo de excepciones funcionan tan bien juntos.

challenge icon

Desafío

Fácil

Construyamos una calculadora de división segura que demuestre el manejo de excepciones en un contexto orientado a objetos. Crearás una clase Calculator que realiza operaciones de división y lanza excepciones descriptivas cuando algo sale mal; después, manejarás esas excepciones de forma adecuada en tu programa principal.

Organizarás tu código en tres archivos:

  • Calculator.h: Define tu clase Calculator, que realiza operaciones matemáticas con un manejo de errores adecuado.

    Tu Calculator debe tener un método divide(double numerator, double denominator) que devuelva el resultado de la división. Sin embargo, si el denominador es cero, debe lanzar un std::runtime_error con el mensaje Division by zero. Si el numerador o el denominador es negativo, debe lanzar un std::invalid_argument con el mensaje Negative values not allowed.

    Incluye también un método safeSqrt(double value) que devuelva la raíz cuadrada del valor. Si el valor es negativo, lanza un std::runtime_error con el mensaje Cannot compute square root of negative number. Necesitarás incluir <cmath> para la función sqrt.

  • Calculator.cpp: Implementa los métodos declarados en tu archivo de encabezado. Asegúrate de incluir los encabezados necesarios (<stdexcept> y <cmath>) y comprueba las condiciones antes de realizar las operaciones.
  • main.cpp: Lee tres entradas, cada una en una línea separada:
    1. Tipo de operación: divide o sqrt
    2. Primer número (double)
    3. Segundo número (double): solo se usa para la división; se ignora para sqrt

    Crea un objeto Calculator y realiza la operación solicitada dentro de un bloque try. Si la operación tiene éxito, imprime Result: [value]. Si se captura una excepción, imprime Error: [message], donde el mensaje proviene del método what() de la excepción.

    Después del bloque try-catch, independientemente de si ocurrió una excepción, imprime Calculation complete para demostrar que el programa continúa ejecutándose después de manejar las excepciones.

Por ejemplo, con las entradas divide, 10 y 2:

Result: 5
Calculation complete

Con las entradas divide, 10 y 0:

Error: Division by zero
Calculation complete

Con las entradas divide, -5 y 2:

Error: Negative values not allowed
Calculation complete

Con las entradas sqrt, 16 y 0:

Result: 4
Calculation complete

Con las entradas sqrt, -9 y 0:

Error: Cannot compute square root of negative number
Calculation complete

Observa cómo el programa maneja los errores adecuadamente al capturar las excepciones y mostrar mensajes descriptivos; después, continúa su ejecución. Este patrón mantiene limpio el manejo de errores y permite que la lógica principal se concentre en el flujo normal.

Pruébalo tú mismo

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

using namespace std;

int main() {
    // Leer entradas
    string operation;
    double num1, num2;
    
    cin >> operation;
    cin >> num1;
    cin >> num2;
    
    // Crear objeto Calculator
    Calculator calc;
    
    // TODO: Usa un bloque try-catch para realizar la operación
    // - Si operation es "divide", llama a calc.divide(num1, num2)
    // - Si operation es "sqrt", llama a calc.safeSqrt(num1)
    // - En caso de éxito, imprime "Result: " seguido del resultado
    // - Captura las excepciones e imprime "Error: " seguido del mensaje de la excepción (usa what())
    // - After the try-catch, always print "Calculation complete"
    
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C++ online