excepciones las excepciones son señales (en forma de objeto) que se generan en ejecución en casos...
Post on 26-Jan-2015
6 Views
Preview:
TRANSCRIPT
Excepciones Las excepciones son señales (en forma de objeto) que se
generan en ejecución en casos de errores, para que puedan ser gestionadas en el programa.
Son un mecanismo para el tratamiento de errores alternativo a los condicionales y las funciones booleanas.
Las excepciones se clasifican por tipos formando jerarquías de clases de excepciones. Además, normalmente transmiten un mensaje indicando el error ocurrido.
En C++ estándar, la raíz de la jerarquía es exception. En C++ Builder, la raíz de la jerarquía es Exception.
Excepciones Las excepciones pueden ser controladas por el programador.
Se pueden lanzar y capturar.
Cuando se genera (se lanza o eleva) una excepción, se transmite automáticamente a través de la pila de llamadas a funciones hasta que es tratada (capturada o interceptada).
Las excepciones deben de tratarse procurando que la aplicación pueda seguir ejecutándose con el menor daño posible, o si no terminando la ejecución del programa.
En general, la función que lanza la excepción puede estar en una determinada unidad o librería, y el código que la trata en otra.
Excepciones: Ejemplo La función StrToInt(AnsiString) genera una excepción si la
cadena que recibe por parámetro no representa sintácticamente un entero válido.
Así StrToInt("12.9") o StrToInt("12a") generan una excepción del tipo EConvertError que indica que no se puede convertir el AnsiString a un valor entero.
Por tanto, al utilizar esta función deberíamos tener en cuenta esta posibilidad cuando no estemos seguros de que la cadena es válida, como cuando la cadena es un dato que se pide al usuario.
Excepciones: Lanzamiento
Para lanzar una excepción:
throw ConstructoraClase(Argumentos);
throw crea un objeto del tipo indicado invocando a la constructora.
Excepciones: Lanzamientoclass ExcepFich{public: AnsiString mensaje; ExcepFich(AnsiString m){mensaje=m;}};
virtual void cargar(ifstream& fich){ string cadena;
fich >> cadena; if (cadena!=‘\\Xini’) throw ExcepFich(“Error de lectura”); else .... }
Excepciones: Sintaxis
En el .h se deben indicar que métodos van a lanzar excepciones y de qué tipo van a ser éstas.
Tipo nombreMetodo(argumentos) throw (A,B,C,...);
A,B,C,.. son nombres de clases. En el .cpp:
Tipo nombreMetodo(argumentos) throw (A,B,C,...){..};
Si no se pone nada puede lanzar excepciones de cualquier tipo.
Excepciones: Sintaxis
En el .h:
virtual void cargar(ifstream& fich) throw (ExcepFich);
En el .cpp:
void Linea::cargar(ifstream& f) throw (ExcepFich)
{.....};
Excepciones: Captura y control
try {
// código que puede generar excepciones
}
catch (Clase1 [& Var1])
{// tratamiento de excepciones de tipo Clase1}
catch (Clase2 [& Var2])
{// tratamiento de excepciones de tipo Clase2}
.....
catch (ClaseN [& VarN])
{// tratamiento de excepciones de tipo ClaseN}
Excepciones: Captura y control
Según se va subiendo por la pila de llamadas en busca de bloques try, sus correspondientes cláusulas catch se prueban secuencialmente en busca de una concordancia.
Mientras no se encuentre la concordancia, seguimos subiendo por la pila de llamadas.
Una concordancia se da cuando la excepción lanzada es una instancia directa o indirecta (subclase) de la especificada en el parámetro del catch.
La siguiente instrucción a un bloque try-catch es la siguiente instrucción que aparece después de todos las cláusulas catch.
Excepciones: Captura y control
class Error{}; // p1 y q1 no hacen nadavoid principal(){try {p1(); p2();p3(); }catch (Error) {ShowMessage(“Capturada en principal");}ShowMessage("Sigo ejecutando por aquí (principal)");}void p2(){p1(); try {q1();q2();q3();} catch (Error) {ShowMessage("Capturada en p2");}ShowMessage("Sigo ejecutando por aquí (p2)");};void p3(){ ShowMessage(“Si que ejecuto p3");};void q2(){try {throw Error();} catch (Error){ShowMessage("Capturada en q2");};
ShowMessage("Sigo ejecutando por aquí (q2)"); }void q3(){ ShowMessage(“Si que ejecuto q3");};
Excepciones: Captura y control
Se muestra por pantalla:
Capturada en q2
Sigo ejecutando por aquí (q2)
Si ejecuto q3
Sigo ejecutando por aquí (p2)
Si ejecuto p3
Sigo ejecutando por aquí (principal)
Excepciones: Captura y control
class Error{}; class Error1{};// p1 y q1 no hacen nada
void principal(){
try {p1(); p2();p3(); }
catch (Error) {ShowMessage(“Capturada en principal");}
ShowMessage("Sigo ejecutando por aquí (principal)");}
void p2(){
p1(); try {q1();q2();q3();}
catch (Error) {ShowMessage("Capturada en p2");}
ShowMessage("Sigo ejecutando por aquí (p2)");};
void p3(){ ShowMessage(“Si que ejecuto p3");};
void q2(){try {throw Error();}
catch (Error1) {ShowMessage("Capturada en q2");};
ShowMessage("Sigo ejecutando por aquí (q2)"); }
Excepciones: Captura y control
Entonces:
Capturada en p2
Sigo ejecutando por aquí (p2)
Si ejecuto p3
Sigo ejecutando por aquí (principal)
Excepciones: Captura y control
class Error{}; class Error1{};void principal(){try {p1(); p2();p3(); }catch (Error) {ShowMessage(“Capturada en principal");}ShowMessage("Sigo ejecutando por aquí (principal)");}void p2(){p1(); try {q1();q2();q3();} catch (Error1) {ShowMessage("Capturada en p2");}ShowMessage("Sigo ejecutando por aquí (p2)");};void q2(){try {throw Error();} catch (Error1) {ShowMessage("Capturada en q2");};
ShowMessage("Sigo ejecutando por aquí (q2)"); }
Excepciones: Captura y control
void q1(){
try {}
catch (Error){ShowMessage("Capturada en q1");}
ShowMessage("Sigo ejecutando por aquí (q1)");
};
void p1(){
try {}
catch (Error) {ShowMessage("Capturada en p1");}
ShowMessage("Sigo ejecutando por aquí (p1)");
};
Excepciones: Captura y control
Entonces:
Sigo ejecutando por aquí (p1)
Sigo ejecutando por aquí (p1)
Sigo ejecutando por aquí (q1)
Capturada en principal
Sigo ejecutando por aquí (principal)
Excepciones: Captura y control
class Error{};
void principal(){
try {p2(); p3();}
catch (Error){ShowMessage(“Capturada en principal");}
ShowMessage("Sigo ejecutando por aquí (principal)");}void p2(){ p1();
try {q1();q2();q3();}
catch (Error){ShowMessage("Capturada en p2");}
ShowMessage("Sigo ejecutando por aquí (p2)");};
void p1(){ throw Error();}
Excepciones: Captura y control
Capturada en principal
Sigo ejecutando por aquí (principal)
Excepciones: Captura y control
Cuando creamos una aplicación nueva, las excepciones que no sean capturadas por el programador, siempre son controladas por la aplicación:
Por las propias librerías gráficas. O por la aplicación (en caso de excepciones propias del
Builder).
Excepciones: Captura y control
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){ try { Application->Initialize(); Application->CreateForm(__classid(TForm1), &Form1); Application->Run(); } catch (Exception &exception) // excepciones del Builder { Application->ShowException(&exception); } return 0;}
Excepciones: Captura y control
Cuando se captura una excepción, el objeto de la excepción es destruido.
En una cláusula catch se puede declarar una variable local ([&Var]) cuyo ámbito es el bloque del tratamiento. Como es un objeto, podemos hacer con él lo que con cualquier otro objeto de esa clase.
En una cláusula catch se puede volver a lanzar la misma excepción mediante throw.
Para capturar cualquier tipo de excepción: catch(...){//tratamiento}
Excepciones: Captura y control
void TForm1::p1(){ try{ p2();} catch (const Error& E){ ShowMessage(E.mensaje); ShowMessage("Capturada en principal");}};//----------------------void TForm1::p2(){ try{ p3();} catch (...){throw;} };//-----------------------void TForm1::p3(){try{ p4();} catch(...){throw;}};//-----------------------void TForm1::p4(){ throw Error("lanzada excepcion en p4");};
Excepciones: La clase Exception
C++Builder contiene muchas clases predefinidas para lanzar excepciones.
Todas ellas derivan de la clase Exception.
Para capturar una excepción de la clase Exception o de alguna de sus derivadas hay que usar la sintaxis:
catch (const Exception &Variable)
Una de las distintas constructoras de Exception es:
Exception(const AnsiString Msg);
Excepciones: La clase Exception
Podemos por tanto lanzar este tipo de excepciones con:
throw Exception(“.......”);
Cuando las capturamos vía un:
catch (const Exception &Variable)
Podemos acceder a su mensaje utilizando la propiedad Message:
Variable.Message
Excepciones: La clase Exception
Si ha sido el propio sistema el que ha lanzado la excepción, también podemos capturar el mensaje que contiene. En este caso el mensaje es el nombre de una subclase de Exception (el tipo del objeto excepción lanzado).
Entre la subclases de Exception destacamos:
EAccessViolation: Acceso de memoria incorrecto. EConvertError: Error de conversión de tipos. EDivByZero: división entre cero. EInOutError: Error de Entrada/salida.
En la ayuda pueden encontrarse todas.
Excepciones: La clase Exception
void p() {
throw Exception(“excepción provocada”);
}
void principal() {
try {p();}
catch (const Exception &E){ShowMessage(E.Message);}
} Se captura la excepción lanzada por p() y se muestra el
mensaje “excepción provocada”
Excepciones: La clase Exception
void p() {
int n1=5;
int n2=0;
int n3=n1/n2; // lanza una excepción de división entre 0
}
void principal() {
try {p();}
catch (const Exception &E){ShowMessage(E.Message);}
}
Se captura la excepción lanzada por p() y se muestra el mensaje “EDivByZero”
Excepciones: La clase Exception
void p() {
int n1=5;
int n2=0;
int n3=n1/n2; // lanza una excepción de división entre 0
}void principal() {
try {p();}
catch (const EDivByZero &E){ShowMessage(“división entre 0”);}
}
Se captura la excepción lanzada por p() y se muestra el mensaje “división entre 0”
Excepciones: Un ejemplo
Excepciones: Un ejemplo
Tipos de errores que pueden aparecer:
Errores de conversión de tipos (de String a Entero).
División entre 0
Excepciones: Un ejemplovoid __fastcall TForm1::BotonOKClick(TObject *Sender){try { int n1=StrToInt(EditPrimerEntero->Text); int n2=StrToInt(EditSegundoEntero->Text); ShowMessage(n1/n2); Close(); }catch (const EConvertError &E) {ShowMessage("Error de conversión"); }catch (const EDivByZero &E) {ShowMessage("División entre 0");}}
Excepciones: Un ejemplo
Se hace un “mal” control de los posibles errores ya que no se muestra información sobre el dato que ha sido mal introducido.
¿Qué pasaría si tuviéramos 100 datos para introducir?
¡¡¡¡ Sería razonable lanzar la excepción en cuanto se detecte que un dato ha sido mal introducido !!!!
Excepciones: Un ejemplovoid __fastcall TForm1::BotonOKClick(TObject *Sender){try { int n1=StrToInt(EditPrimerEntero->Text); continuaPidiendoDatos(n1); }catch (const EConvertError &E) {ShowMessage("Meta un entero como primer entero"); ActiveControl=EditPrimerEntero;
EditPrimerEntero->Text=""; LabelPrimerEntero->Font->Color=clBlue;}}
Excepciones: Un ejemplovoid TForm1::continuaPidiendoDatos(int n1) { try { LabelPrimerEntero->Font->Color=clBlack; int n2=StrToInt(EditSegundoEntero->Text); if (n2==0) throw EDivByZero("El segundo entero NO puede ser 0"); else {LabelSegundoEntero->Font->Color=clBlack; ShowMessage(n1/n2); Close(); } }
Excepciones: Un ejemplocatch (EConvertError &E) { ShowMessage("Meta un entero como segundo entero"); ActiveControl=EditSegundoEntero;
EditSegundoEntero->Text=""; LabelSegundoEntero->Font->Color=clBlue; }catch (const EDivByZero &E) { ShowMessage(E.Message); ActiveControl=EditSegundoEntero; EditSegundoEntero->Text=""; LabelSegundoEntero->Font->Color=clBlue;}}}
Excepciones: Último ejemplo
for (int i=0; i<n; i++){
try{
Ai;
}
catch(...){...}
}
try
for (int i=0; i<n; i++) Ai;
catch(...){...}
top related