La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Desarrollador Profesional de Juegos Programación III Unidad I Excepciones Tipos.

Presentaciones similares


Presentación del tema: "Desarrollador Profesional de Juegos Programación III Unidad I Excepciones Tipos."— Transcripción de la presentación:

1 Desarrollador Profesional de Juegos Programación III Unidad I Excepciones Tipos

2 Durante la ejecución de un programa pueden existir dos tipos de excepciones Síncronas : Son las que ocurren dentro del programa. Ejemplo, que se agote la memoria o cualquier otro tipo de error. Son las tratadas en la unidad 1y como vimos: "las excepciones son condiciones excepcionales que pueden ocurrir dentro del programa..." y las únicas que se consideran. Asíncronas Son las que tienen su origen fuera del programa, a nivel del Sistema Operativo. Por ejemplo que se pulsen las teclas Ctrl+C. Generalmente las implementaciones C++ solo consideran las excepciones síncronas, de forma que no se pueden capturar con ellas excepciones tales como la pulsación de una tecla. Osea solo pueden manejar las excepciones lanzadas con la sentencia throw. Siguen un modelo denominado de excepciones síncronas con terminación, lo que significa que una vez que se ha lanzado una excepción, el control no puede volver al punto que la lanzó. El "handler" no puede devolver el control al punto de origen del error mediante una sentencia return. En este contexto, un return en el bloque catch supone salir de la función que contiene dicho bloque. El sistema Estándar C++ de manejo de excepciones no está diseñado para manejar directamente excepciones asíncronas, aunque pueden implementarse medidas para su control. Además las implementaciones más comunes tienen recursos para manejar las excepciones del S.O. C++ Builder con la librería VCL dispone de los mecanismos adecuados para manejar excepciones de Windows-32(asíncronas).

3 Manejo de excepciones en C++ Secuencia de ejecución La filosofía C++ respecto al manejo de excepciones no consiste en corregir el error y volver al punto de partida. Por el contrario, cuando se genera una excepción el control sale del bloque-intento try que lanzó la excepción (incluso de la función), y pasa al bloque catch cuyo manejador corresponde con la excepción lanzada (si es que existe). A su vez el bloque catch puede hacer varias cosas: –Relanzar la misma excepción. –Saltar a una etiqueta –Terminar su ejecución normalmente (alcanzar la llave } de cierre). Si el bloque-catch termina normalmente sin lanzar una nueva excepción, el control se salta todos los bloques-catch que hubiese a continuación y sigue después del último. Puede ocurrir que el bloque-catch lance a su vez una excepción. Lo que nos conduce a excepciones anidadas. Esto puede ocurrir, por ejemplo, cuando en el proceso de limpieza de pila ("Stack unwinding") que tienen lugar tras una excepción, un destructor lanza una excepción. Como veremos en los ejemplos, además del manejo y control de errores, las excepciones C++ pueden utilizarse como un mecanismo de return o break multinivel, controlado no por una circunstancia excepcional, sino como un acto deliberado del programador para controlar el flujo de ejecución

4 Lanzar una excepción try { // bloque-intento... } Durante la ejecución de este bloque, el proceso sigue los siguientes pasos: a: Se produce una circunstancia excepcional: Se lanza la excepción señalada por la sentencia throw El programa busca por un manejador ("handler") adecuado a la excepción a1 Se encuentra el "handler" La pila (stack) es recorrida hacia abajo hasta el punto donde está el manejador. El control del programa es transferido al manejador. a2 No se encuentra ningún manejador ( 1.6.3 Excepciones imprevistas).1.6.3 Se invoca la función terminate() a2a Se ha establecido una función t_func por defecto con set_terminate(). terminate invoca t_func (que debe terminar el programa). a2b No se ha establecido ninguna función por defecto con set_terminate() terminate invoca la función abort(). b: No se produce ninguna excepción: El programa sigue su ejecución normal (saltándose los bloques catch que pudieran seguir).

5 Se lanza una excepción Las excepciones se lanzan mediante una sentencia throw que obligatoriamente debe estar situada en el interior de un bloque try (o en un bloque o función anidada en él). También obligatoriamente debe seguir, al menos un bloque catch Ejemplo 1: se pasa el objeto Out al manejador catch de la línea 10. 1.#include 2.bool ok; 3.class Out { }; // instancia el objeto a lanzar 4.void foo(bool pvez); // prototipo funcion 5.int main() { 6. try { // bloque try 7. ok = true; 8. foo(true); 9. } 10. catch (Out o) { // manejador (la excepción es capturada aquí) 11. ok = false; // valor de pass si se produce una excepción 12. } return ok ? (cout<<"Acierto!“<<,0) : (cout<<"Fallo!“<<,1); } 13. void foo(bool pvez){ // definición de foo 14. if ( pvez ) {Obj o; throw o; } // lanzar excepción 15.} Salida: Fallo!

6 Explicación El bloque-intento try que comienza en L.6 y el manejador catch que comienza en L.10, forman el mecanismo de excepción junto con la clase Out que sirve para instanciar el objeto que se lanzará si se produce una excepción. Cualquier excepción lanzada dentro del bloque try será capturada en la línea 10 (si es del tipo adecuado). Observese que catch y su bloque (L10-12) son en realidad como una función que devolviera void y que debe recibir un tipo Out. El control será transferido a L.10 si la excepción es del este tipo, lo que efectivamente sucede, ya que la sentencia de L.17 indica que la excepción lanzada o, es un objeto tipo Out. Después de ejecutado el bloque catch el control del programa sigue en L.13. Observe que la sentencia L.16 podría haberse sustituido por: if( pvez) throw Out(); // L.16 a: Lanzar excepción. más compacta pero equivalente, ya que Out(), es una invocación al constructor por defecto de la clase, que produce un objeto exactamente igual al objeto o producido en la sentencia Obj o. Observe también que en este caso no se trata propiamente de un error, puesto que la excepción es lanzada inevitablemente. Aquí el mecanismo de excepción se utiliza más bien como un sistema de return multinivel.

7 Relanzar una excepción Si se ha lanzado previamente una excepción y se está en el bloque que la ha capturado, es posible repetir el lanzamiento de la excepción (el mismo objeto recibido en el bloque catch) utilizando simplemente la sentencia throw sin ningún especificador. Ojo que el lanzamiento throw, solo puede realizarse desde el interior de un bloque try, al que debe seguir su correspondiente "handler". Ejemplo Erroneo try {... if (x) throw A(); // lanzar excepción } catch (A a) { // capturar excepción... // hacer algo respecto al error throw; // Error!! no está en un bloque try } Versión correcta: try {... if (x) throw A(); // lanzar excepción } catch (A a) { // capturar excepción... // hacer algo respecto al error try { throw; // Ok. relanza excepción A } catch (A a) { // capturar excepción... }

8 Relanzar una excepción Otra ejemplo correcto: void foo(); void main () { try { // Bloque-T1... foo(); } catch (A a) { // L.7: capturar excepción... // L.8: hacer algo respecto al error } return 0; } void foo() {... if (x) try { // Bloque-T2 throw A(); // L.15: Ok. lanza excepción A } catch (A) { // L.17:... // hacer algo respecto al error throw; // L.19: Ok. relanzar excepcion A }

9 #include Ejemplo completo using namespace std; void foo(bool); int main() { try { foo(false); } // M.1: catch(char* a){ cout << "Recibida excepcion " << a << " en main\n"; return 0; } cout << "No ha pasado nada\n"; return 0; } void foo(bool b){ if ( !b ) try { cout << "Recibido Falso en foo, lanzando excepcion\n"; throw "Falso"; } catch (char*) { cout << "Excepcion capturada en foo\n"; throw; // relanzar excepción } } Salida: Recibido Falso en foo, lanzando excepción Excepción capturada en foo Recibida excepción Falso en main Si cambiamos false por true en M.1: Salida No ha pasado nada\n

10 Ejemplo 2. Muestra como el manejador de una excepción puede relanzar la excepción recibida (en ese momento debe existir una excepción en curso). #include using namespace std; bool ok = true; class A{ }; void test(); // prototipo void foo(bool); // prototipo int main() { try { test(); } catch(A& a){ ok = true; } ok ? (cout << "Correcto\n") : (cout << "Incorrecto\n"); return ok ? 1 : 0; } void test() { try { foo(true); } catch(A& a) { ok ? (cout << "Correcto\n") : (cout << "Incorrecto\n"); ok = false; throw; // se relanza la excepción A } } void foo(bool b){ b ? (cout << "Lanzar A\n") : (cout << "No lanzar A\n"); if(b) throw A(); } Salida Lanzar A Correcto Correcto

11 Ejemplo 3. Cuando ocurre una excepción la expresión throw inicializa un objeto temporal del tipo X correspondiente al argumento utilizado en la expresión throw(X arg). El compilador puede generar otras copias, en consecuencia, como se muestra aquí, puede ser útil definir un constructor de copias para el objeto usado en la excepción. #include class foo { public: foo() { cout<<"Hacer un foo";} // constructor por defecto foo(const foo&){ cout<<"Copiando un foo"; } // constructor copia ~foo() {cout<<"Destruyendo un festival"; } // destructor }; int main() { try { cout<<"Lanzando un foo"); throw( foo() ); } catch(foo&){ cout<<"Capturando un festival" ; } return 0; } Salida: Lanzando un foo Hacer un foo Copiando un foo Destruyendo un foo Capturando un foo Destruyendo un foo


Descargar ppt "Desarrollador Profesional de Juegos Programación III Unidad I Excepciones Tipos."

Presentaciones similares


Anuncios Google