martes, 3 de junio de 2014

C++ - Herencia: "exception"

Herencia: "exception"

En esta entrada, veremos un ejemplo de herencia y de funciones virtuales, usando como base de la explicación la clase "std::exception" de la librería estandar.



Para empezar: La clase exception es una clase utilizada en la librería estándar para unificar el manejo de excepciones. Las excepciones que puedes lanzar en C++ son de cualquier tipo, ya sean tipos básicos u objetos.
Se capturan mediante el uso de las sentencias try{ /* ... */}catch( tipo variable ){ /* ... */}. Si queremos capturar una excepción de la librería estándar, basta poner "exception& e" en el catch.

Ahora volviendo al tema: Si creamos una clase, y hacemos que herede de std::exception, podremos lanzar y capturar esa clase con el mismo catch. De hecho, al colocar "exception& e", estamos cogiendo la variable por referencia, y dado que nuestro objeto hereda de exception, podremos usar sus funciones virtuales.

La función virtual principal de la clase exception es la función "what()", que retorna una cadena con el error ocurrido. Veamos un ejemplo:


#include<iostream>
#include<exception>

using namespace std;

class exc:public exception{
/* */
};

int main(){}


Importante incluir la librería exception para poder usar la clase exception.

Una vez puesta la base, vamos a la función virtual más importante:


virtual const char* what() const throw(){
    return "Error";
}


Hasta aquí lo más básico. Luego, como otra clase cualquiera, la podéis personalizar como queráis. Aquí pongo una clase que hice yo de este modo:


class exc:public exception{
    string _msg;
public:
    exc(string msg="Error - Exception"):_msg(msg){}
    exc(int error_code){
        _msg = "Error " + to_string(error_code);
    }
    exc(const exc& e):_msg(e.what()){}

    exc operator=(const exc& e){_msg = e.what();}
    exc operator=(string s){_msg = s;}
    exc operator=(int error_code){
        _msg = "Error " + to_string(error_code);
    }
    virtual const char* what() const throw(){
        return _msg.c_str();
    }
};


Prácticamente creé 3 constructores (y 3 operator= equivalentes), y guardo los datos en la string _msg.

El primero de los constructores recoge una string, y directamente iguala el _msg con ella.
El segundo de ellos, recoge un entero a modo de error, y genera un mensaje del tipo "Error " + código haciendo uso de to_string(), que transforma un número a una string.
El tercero de ellos es el constructor de copia.

La función virtual what(), lo único que hace es retornar el _msg. (Como la función es del tipo const char*, retorna _msg.c_str(), que retorna la cadena constante de char.

Aunque realmente no es un código complejo, siempre puede ser útil generar excepciones propias.

Esto es un código ya listo para quien quiera probar:


#include<iostream>
#include<exception>

using namespace std;

class exc:public exception{
    string _msg;
public:
    exc(string msg="Error - Exception"):_msg(msg){}
    exc(int error_code){
        _msg = "Error " + to_string(error_code);
    }
    exc(const exc& e):_msg(e.what()){}

    exc operator=(const exc& e){_msg = e.what();}
    exc operator=(string s){_msg = s;}
    exc operator=(int error_code){
        _msg = "Error " + to_string(error_code);
    }
    virtual const char* what() const throw(){
        return _msg.c_str();
    }
};

double div(double a, double b){
    if(b==0) throw exc(666);
    return a/b;
}

int main(){
    try{
        cout << div(56.0 , 0.0) << endl;
    }catch(exception& e){
        cout << e.what() << endl;
    }
    return 0;
}


Y hasta aquí esta entrada. Hacía ya un tiempo que no sacaba nada, así que se me ocurrió sacar algo del tema herencia. Y de paso, excepciones. Dos pájaros de un tiro.

Suerte, y adiós ;D

No hay comentarios:

Publicar un comentario