En C++, las excepciones son anomalías en tiempo de ejecución o condiciones anormales que encuentra un programa durante su ejecución. El proceso de manejar estas excepciones se llama manejo de excepciones. Utilizando el mecanismo de manejo de excepciones, el control de una parte del programa donde ocurrió la excepción se puede transferir a otra parte del código.
Básicamente, usando el manejo de excepciones en C++, podemos manejar las excepciones para que nuestro programa siga ejecutándose.
json en ejemplo json
¿Qué es una excepción de C++?
Una excepción es un problema inesperado que surge durante la ejecución de un programa. Nuestro programa finaliza repentinamente con algunos errores/problemas. La excepción ocurre durante la ejecución del programa (tiempo de ejecución).
Tipos de excepción de C++
Hay dos tipos de excepciones en C++.
- Sincrónico: Excepciones que ocurren cuando algo sale mal debido a un error en los datos de entrada o cuando el programa no está equipado para manejar el tipo de datos actual con el que está trabajando, como dividir un número por cero.
- Asincrónico : Excepciones que están fuera del control del programa, como fallas del disco, interrupciones del teclado, etc.
C ++ intenta capturar
C++ proporciona una característica incorporada para el manejo de excepciones. Se puede hacer utilizando las siguientes palabras clave especializadas: intentar, atrapar y lanzar, cada una con un propósito diferente.
Sintaxis de try-catch en C++
try { // Code that might throw an exception throw SomeExceptionType('Error message'); } catch ( ExceptionName e1 ) { // catch block catches the exception that is thrown from try block }> 1. prueba en C++
La palabra clave try representa un bloque de código que puede generar una excepción colocada dentro del bloque try. Le siguen uno o más bloques de captura. Si se produce una excepción, el bloque try genera esa excepción.
2. atrapar en C ++
La declaración catch representa un bloque de código que se ejecuta cuando se lanza una excepción particular desde el bloque try. El código para manejar la excepción está escrito dentro del bloque catch.
3. agregue C ++
Se puede generar una excepción en C++ usando la palabra clave throw. Cuando un programa encuentra una declaración de lanzamiento, inmediatamente finaliza la función actual y comienza a buscar un bloque catch coincidente para manejar la excepción lanzada.
Nota: Se pueden utilizar varias declaraciones catch para detectar diferentes tipos de excepciones lanzadas por el bloque try.
Las palabras clave try y catch vienen en pares: usamos el bloque try para probar algún código y, si el código arroja una excepción, lo manejaremos en nuestro bloque catch.
Por qué necesitamos ¿Manejo de excepciones en C++?
Las siguientes son las principales ventajas del manejo de excepciones sobre el manejo de errores tradicional:
- Separación del código de manejo de errores del código normal : Siempre existen condiciones if-else para manejar errores en los códigos de manejo de errores tradicionales. Estas condiciones y el código para manejar errores se mezclan con el flujo normal. Esto hace que el código sea menos legible y mantenible. Con los bloques try/catch, el código para el manejo de errores se separa del flujo normal.
- Las funciones/métodos pueden manejar solo las excepciones que elijan : Una función puede generar muchas excepciones, pero puede optar por manejar algunas de ellas. Las otras excepciones, que se generan pero no se detectan, pueden ser manejadas por la persona que llama. Si la persona que llama elige no detectarlas, entonces las excepciones son manejadas por la persona que llama.
En C++, una función puede especificar las excepciones que genera utilizando la palabra clave throw. La persona que llama a esta función debe manejar la excepción de alguna manera (ya sea especificándola nuevamente o detectándola).
- Agrupación de tipos de errores : En C++, tanto los tipos básicos como los objetos se pueden generar como excepciones. Podemos crear una jerarquía de objetos de excepción, agrupar excepciones en espacios de nombres o clases y categorizarlas según sus tipos.
Ejemplos de manejo de excepciones en C++
Los siguientes ejemplos demuestran cómo utilizar un bloque try-catch para manejar excepciones en C++.
Ejemplo 1
El siguiente ejemplo demuestra cómo lanzar excepciones en C++.
C++
// C++ program to demonstate the use of try,catch and throw> // in exception handling.> #include> #include> using> namespace> std;> int> main()> {> >// try block> >try> {> >int> numerator = 10;> >int> denominator = 0;> >int> res;> >// check if denominator is 0 then throw runtime> >// error.> >if> (denominator == 0) {> >throw> runtime_error(> >'Division by zero not allowed!'>);> >}> >// calculate result if no exception occurs> >res = numerator / denominator;> >//[printing result after division> >cout <<>'Result after division: '> << res << endl;> >}> >// catch block to catch the thrown exception> >catch> (>const> exception& e) {> >// print the exception> >cout <<>'Exception '> << e.what() << endl;> >}> >return> 0;> }> |
>
>Producción
Exception Division by zero not allowed!>
Ejemplo 2
El siguiente es un ejemplo sencillo para mostrar el manejo de excepciones en C++. El resultado del programa explica el flujo de ejecución de los bloques try/catch.
CPP
// C++ program to demonstate the use of try,catch and throw> // in exception handling.> #include> using> namespace> std;> int> main()> {> >int> x = -1;> >// Some code> >cout <<>'Before try
'>;> >// try block> >try> {> >cout <<>'Inside try
'>;> >if> (x <0) {> >// throwing an exception> >throw> x;> >cout <<>'After throw (Never executed)
'>;> >}> >}> >// catch block> >catch> (>int> x) {> >cout <<>'Exception Caught
'>;> >}> >cout <<>'After catch (Will be executed)
'>;> >return> 0;> }> |
>
>Producción
Before try Inside try Exception Caught After catch (Will be executed)>
Propiedades del manejo de excepciones en C++
Propiedad 1
Hay un bloque catch especial llamado bloque 'catch-all', escrito como catch(...), que se puede utilizar para detectar todo tipo de excepciones.
Ejemplo
En el siguiente programa, se lanza un int como excepción, pero no hay un bloque catch para int, por lo que se ejecutará el bloque catch(…).
CPP
// C++ program to demonstate the use of catch all> // in exception handling.> #include> using> namespace> std;> int> main()> {> >// try block> >try> {> >// throw> >throw> 10;> >}> >// catch block> >catch> (>char>* excp) {> >cout <<>'Caught '> << excp;> >}> >// catch all> >catch> (...) {> >cout <<>'Default Exception
'>;> >}> >return> 0;> }> |
>
>Producción
Default Exception>
Propiedad 2
La conversión de tipos implícita no ocurre para los tipos primitivos.
Ejemplo
si no en java
En el siguiente programa, 'a' no se convierte implícitamente a int.
CPP
//// C++ program to demonstate property 2: Implicit type> /// conversion doesn't happen for primitive types.> // in exception handling.> #include> using> namespace> std;> int> main()> {> >try> {> >throw> 'a'>;> >}> >catch> (>int> x) {> >cout <<>'Caught '> << x;> >}> >catch> (...) {> >cout <<>'Default Exception
'>;> >}> >return> 0;> }> |
ejecutar scripts en Linux
>
>Producción
Default Exception>
Producción:
Default Exception>
Propiedad 3
Si se lanza una excepción y no se detecta en ninguna parte, el programa finaliza de forma anormal.
Ejemplo
En el siguiente programa, se lanza un carácter, pero no hay ningún bloque catch para capturarlo.
CPP
// C++ program to demonstate property 3: If an exception is> // thrown and not caught anywhere, the program terminates> // abnormally in exception handling.> #include> using> namespace> std;> int> main()> {> >try> {> >throw> 'a'>;> >}> >catch> (>int> x) {> >cout <<>'Caught '>;> >}> >return> 0;> }> |
>
>
Producción
terminate called after throwing an instance of 'char'>
Podemos cambiar este comportamiento de terminación anormal escribiendo nuestra función inesperada.
Nota : Una excepción de clase derivada debe detectarse antes que una excepción de clase base.
Al igual que Java, la biblioteca C++ tiene una excepción estándar class que es la clase base para todas las excepciones estándar. Todos los objetos generados por los componentes de la biblioteca estándar se derivan de esta clase. Por lo tanto, todas las excepciones estándar se pueden detectar detectando este tipo.
Propiedad 4
A diferencia de Java, en C++, todas las excepciones no están marcadas, es decir, el compilador no verifica si se detecta una excepción o no (consulte este para detalles). Por lo tanto, no es necesario especificar todas las excepciones no detectadas en una declaración de función. Sin embargo, el manejo de excepciones es una práctica recomendada.
Ejemplo
El siguiente programa se compila bien, pero idealmente, la firma de fun() debería enumerar las excepciones no verificadas.
CPP
// C++ program to demonstate property 4 in exception> // handling.> #include> using> namespace> std;> // This function signature is fine by the compiler, but not> // recommended. Ideally, the function should specify all> // uncaught exceptions and function signature should be> // 'void fun(int *ptr, int x) throw (int *, int)'> void> fun(>int>* ptr,>int> x)> {> >if> (ptr == NULL)> >throw> ptr;> >if> (x == 0)> >throw> x;> >/* Some functionality */> }> int> main()> {> >try> {> >fun(NULL, 0);> >}> >catch> (...) {> >cout <<>'Caught exception from fun()'>;> >}> >return> 0;> }> |
>
>Producción
pila en java
Caught exception from fun()>
Una mejor manera de escribir el código anterior:
CPP
// C++ program to demonstate property 4 in better way> #include> using> namespace> std;> // Here we specify the exceptions that this function> // throws.> void> fun(>int>* ptr,>int> x)>throw>(> >int>*,>int>)>// Dynamic Exception specification> {> >if> (ptr == NULL)> >throw> ptr;> >if> (x == 0)> >throw> x;> >/* Some functionality */> }> int> main()> {> >try> {> >fun(NULL, 0);> >}> >catch> (...) {> >cout <<>'Caught exception from fun()'>;> >}> >return> 0;> }> |
>
>Producción
Caught exception from fun()>
Nota : El uso de la especificación de excepción dinámica ha quedado obsoleto desde C++ 11. Una de las razones puede ser que puede cancelar aleatoriamente su programa. Esto puede suceder cuando se lanza una excepción de otro tipo que no se menciona en la especificación de excepción dinámica. Su programa se abortará porque en ese escenario, llama (indirectamente) a terminate(), que de forma predeterminada llama a abort().
Propiedad 5
En C++, los bloques try/catch se pueden anidar. Además, se puede volver a lanzar una excepción usando throw; .
Ejemplo
El siguiente programa muestra el anidamiento de bloques try/catch.
CPP
// C++ program to demonstrate try/catch blocks can be nested> // in C++> #include> using> namespace> std;> int> main()> {> >// nesting of try/catch> >try> {> >try> {> >throw> 20;> >}> >catch> (>int> n) {> >cout <<>'Handle Partially '>;> >throw>;>// Re-throwing an exception> >}> >}> >catch> (>int> n) {> >cout <<>'Handle remaining '>;> >}> >return> 0;> }> |
>
>Producción
Handle Partially Handle remaining>
Una función también puede volver a lanzar una función usando el mismo lanzamiento; sintaxis. Una función puede manejar una parte y pedirle a la persona que llama que maneje el resto.
Propiedad 6
Cuando se lanza una excepción, todos los objetos creados dentro del bloque try adjunto se destruyen antes de que el control se transfiera al bloque catch.
Ejemplo
El siguiente programa demuestra la propiedad anterior.
CPP
// C++ program to demonstrate> #include> using> namespace> std;> // Define a class named Test> class> Test {> public>:> >// Constructor of Test> >Test() { cout <<>'Constructor of Test '> << endl; }> >// Destructor of Test> >~Test() { cout <<>'Destructor of Test '> << endl; }> };> int> main()> {> >try> {> >// Create an object of class Test> >Test t1;> >// Throw an integer exception with value 10> >throw> 10;> >}> >catch> (>int> i) {> >// Catch and handle the integer exception> >cout <<>'Caught '> << i << endl;> >}> }> |
>
>Producción
Constructor of Test Destructor of Test Caught 10>
Limitaciones del manejo de excepciones en C++
El manejo de excepciones en C++ también tiene algunas limitaciones:
- Las excepciones pueden romper la estructura o el flujo del código, ya que se crean múltiples puntos de salida invisibles en el código, lo que dificulta su lectura y depuración.
- Si el manejo de excepciones no se realiza correctamente también puede provocar fugas de recursos.
- Es difícil aprender a escribir código de excepción que sea seguro.
- No existe un estándar de C++ sobre cómo utilizar el manejo de excepciones, por lo que existen muchas variaciones en las prácticas de manejo de excepciones.
Conclusión
El manejo de excepciones en C++ se utiliza para manejar sucesos inesperados utilizando bloques try y catch para gestionar el problema de manera eficiente. Este manejo de excepciones hace que nuestros programas sean más confiables ya que los errores en tiempo de ejecución se pueden manejar por separado y también ayuda a evitar que el programa falle y finalice abruptamente cuando se encuentra un error.
números romanos 1 100
Artículos relacionados:
- Principales preguntas y respuestas de la entrevista sobre manejo de excepciones de C++
- Cuestionario sobre manejo de excepciones en C++