1 Desarrollador Profesional de Juegos Programación III Unidad I El manejador universal
2 También existe la posibilidad de definir un manejador que pueda capturar cualquier excepción. La sintaxis es la siguiente: catch (...) { } La sentencia catch captura cualquier excepción sin importar el tipo. Existe solamente un catch para el bloque try. Ejemplo: #include using namespace std; bool ok; class Out { }; void foo(bool pvez) { if (pvez) throw Out(); } void test() try { foo(true); } catch(...){ ok = true; } // puede capturar cualquier excepción } int main() { ok = false; test(); return ok ? (cout
3 Salto a una etiqueta Es posible también utilizar un sentencia goto para transferir el control del programa afuera de un manejador. Vemos el ejemplo visto en el modulo 2 modificado. #include bool ok; class Out { }; // Clase para instanciar el objeto a lanzar void foo(bool pvez); // prototipo de una funcion int main() { try { // bloque try ok = true; foo( true ); } catch( Out o) { // manejador que captura la excepción goto fallo; // salta a la etiqueta fallo } return (cout
4 Las excepciones pueden ser anidadas a cualquier nivel (existir bloques try dentro de otros bloques try y bloques catch). Para mantener la regla que indica que un bloque try debe ser seguido inevitablemente por un catch, entonces pueden existir secuencias try-catch dentro de bloques try y de bloques catch. Excepciones anidadas Secuencias anidadas en el try. class Error { }; void foo () {... try { // Bloque-intento 1... try { // Bloque-intento en 1.1... } catch { // Handler de 1.1 captura excepciones de 1.1 }... // continúa bloque 1 } catch (Error) { //Handler de 1: captura excepciones de 1 }... // sigue a bloque 1 } Secuencias anidadas en el catch class Error { }; void foo () {... try { // Bloque-intento 1... } catch (Error) { // Handler de 1: captura excepciones de 1 try { // Bloque-intento en Handler-H1... } catch { // Handler de H1.1 captura excepc. de H1.1 }... // continúa handler H1 }... // sigue a bloque 1 }
5 Ejemplo 1: #include class Base{ }; class Derivada1: public Base{ }; class Derivada2: public Base{ }; void foo(int valor); int main() { try { foo(0); } catch(const Derivada1&) { cout
6 Ejemplo 2: Vemos que cuando se captura una excepción y esta pertenece a una jerarquía de clases, se comienza por la clase más derivada, sino se pierde la capacidad de discriminar el tipo de excepción acontecido. class Base{ }; class Derivada1: public Base{ }; class Derivada2: public Base{ }; void foo( int valor) { switch(valor){ case 1 : throw( Derivada1() ); break; case 2 : throw( Derivada2() ); break; default : throw( Base() ); break; } int main() { try { foo(0); } // estas sentencias están en el orden adecuado catch(const Derivada1&) { cout
7 … try { foo(1); } catch(const Base& ) { cout
8 Para solucionar el diseño anterior podríamos capturar solamente las excepciones de la clase-base y usar polimorfismo para discriminar la excepción: #include using namespace std; class Base { public: virtual void cartel() { cout
9 int main() { try { foo(0); } catch(Base& f) { f.cartel(); } try { foo(1); } catch(Base& f) { f.cartel(); } try { foo(2); } catch(Base& f) { f.cartel(); } return 0; } Salida Base Estoy en Derivada1 Estoy en Derivada2