#include <iostream>
#include <stdexcept>

using namespace std;

class Exception : public runtime_error {
    public:
        Exception(const string msg) : runtime_error(msg) {}
        virtual void raise() { throw *this; }
};

class DerivedException : public Exception {
    public:
        DerivedException(const string msg) : Exception(msg) {}
        virtual void raise() { throw *this; }
};

void
ProcessThrowedException(Exception& e) {
    cout << " ** Excepción procesada como: ";
    try {
        throw e;
    } catch(DerivedException& e) {
        cout << "DerivedException" << endl;
    } catch(Exception& e) {
        cout << "Exception" << endl;
    }
}

void
ProcessRaisedException(Exception& e) {
    cout << " ** Excepción procesada como: ";
    try {
        e.raise();
    } catch(DerivedException& e) {
        cout << "DerivedException" << endl;
    } catch(Exception& e) {
        cout << "Exception" << endl;
    }
}

int
main() {
    try {
        cout << "Lanzando excepción 'DerivedException'..." << endl;
        throw DerivedException("Información del error.");
    } catch(Exception& e) {
        cout << "Excepción atrapada." << endl;
        cout << "Procesando excepción atrapada relanzándola con 'throw'..." << endl;
        ProcessThrowedException(e);
        cout << "Procesando excepción atrapada relanzándola con el método virtual 'raise()'..." << endl;
        ProcessRaisedException(e);
    }
}


