Manejo de excepciones en C ++

Manejo de excepciones en C ++
Hay tres tipos de errores de software que existen. Estos son errores de sintaxis, errores lógicos y errores de tiempo de ejecución.

Errores de sintaxis

Una expresión, declaración o construcción erróneamente escrita es un error de sintaxis.

Considere las siguientes dos declaraciones:

int arr [] = 1, 2, 3; //correcto
int arr = 1, 2, 3; // Error de sintaxis, falta []

Son definiciones de la misma matriz. El primero es correcto. Falta el segundo [], y ese es un error de sintaxis. Un programa con un error de sintaxis no tiene éxito para compilar. La compilación falla con un mensaje de error que indica el error de sintaxis. Lo bueno es que siempre se puede solucionar un error de sintaxis si el programador sabe lo que está haciendo.

Error lógico

Un error lógico es un error cometido por el programador cuando se realiza una codificación lógica incorrecta. Puede ser el resultado de la ignorancia del programador a las características del lenguaje de programación o un malentendido de lo que debe hacer el programa.

En esta situación, el programa se compila con éxito. El programa funciona bien, pero produce resultados incorrectos. Tal error puede deberse a hacer un bucle iterar 5 veces cuando se hace para iterar 10 veces. También puede ser que un bucle esté hecho inconscientemente para iterar infinitamente. La única forma de resolver este tipo de error es realizar una programación cuidadosa y probar el programa a fondo antes de entregarlo al cliente.

Errores de tiempo de ejecución

Las entradas incorrectas o excepcionales causan errores de tiempo de ejecución. En este caso, el programa se compiló con éxito y funciona bien en muchas situaciones. En ciertas situaciones, el programa se bloquea (y se detiene).

Imagine que en un segmento de código de programa, 8 debe ser dividido por varios denominadores. Entonces, si el numerador 8 está dividido por el denominador 4, la respuesta (cociente) sería 2. Sin embargo, si el usuario ingresa 0 como denominador, el programa se bloquearía. La división por 0 no está permitida en matemáticas, y tampoco está permitido en la computación. División por cero debe prevenirse en la programación. El manejo de excepciones maneja los errores de tiempo de ejecución, como la división por cero. El siguiente programa muestra cómo manejar el problema de división por cero sin usar la función de excepción en C ++:

#incluir
usando el espacio de nombres STD;
int main ()

int numerator = 8;
int denominator = 2;
if (denominador != 0)

int resultado = numerator/denominator;
cout << result << '\n';

demás

cout << "Division by zero is not permitted!" << '\n';

regresar 0;

La salida es 4. Si el denominador fuera 0, la salida habría sido:

"No se permite la división por cero!"

El código principal aquí es una construcción if-else. Si el denominador no es 0, la división tendrá lugar; Si es 0, la división no tendrá lugar. Se enviará un mensaje de error al usuario, y el programa continúa ejecutándose sin bloquear. Los errores de tiempo de ejecución generalmente se manejan evitando la ejecución de un segmento de código y enviando un mensaje de error al usuario.

La función de excepción en C ++ usa un bloque de try para el bloque if y un bloque de captura para el más bloque para manejar el error, tal como lo sigue:

#incluir
usando el espacio de nombres STD;
int main ()

int numerator = 8;
int denominator = 2;
intentar

if (denominador != 0)

int resultado = numerator/denominator;
cout << result << '\n';

demás

tirar 0;


Catch (int err)

if (err == 0)
cout << "Division by zero is not permitted!" << '\n';

regresar 0;

Tenga en cuenta que el encabezado try no tiene argumento. También tenga en cuenta que el bloque de captura, que es como una definición de función, tiene un parámetro. El tipo de parámetro debe ser el mismo que el operando (argumento) de la expresión de lanzamiento. La expresión de lanzamiento está en el bloque de try. Lanza un argumento de la elección del programador que está relacionada con el error, y el bloque de captura lo atrapa. De esa manera, el código en el bloque de try no se ejecuta. Luego, el bloque de captura muestra el mensaje de error.

Este artículo explica el manejo de excepciones en C++. El conocimiento básico en C ++ es un requisito previo para que el lector comprenda este artículo.

Contenido del artículo:

  • Función lanzando una excepción
  • Más de un bloque de captura para un bloque de intentos
  • Bloques de try/captación anidados
  • Noxcept-especificador
  • La función STD :: Terminate () especial
  • Conclusión

Función Lanzar una excepción:

Una función también puede lanzar una excepción al igual que lo que hace el bloque de intentos. El lanzamiento tiene lugar dentro de la definición de la función. El siguiente programa ilustra esto:

#incluir
usando el espacio de nombres STD;
nulo fn (const char* str)

if (islower (str [0]))
tirar 'l';

int main ()

intentar

fn ("Smith");

Catch (Char Ch)

if (ch == 'l')
cout << "Person's name cannot begin in lowercase!" << '\n';

regresar 0;

Observe que esta vez, el bloque de try tiene solo la llamada de función. Es la función llamada que tiene la operación de lanzamiento. El bloque de captura captura la excepción y la salida es:

"El nombre de la persona no puede comenzar en minúsculas!"

Esta vez, el tipo arrojado y atrapado es un carbón.

Más de un bloqueo de captura para un bloque de intentos:

Puede haber más de un bloque de captura para un bloque de intentos. Imagine la situación en la que una entrada puede ser cualquiera de los caracteres del teclado, pero no un dígito y no un alfabeto. En este caso, debe haber dos bloques de captura: uno para un entero para verificar el dígito y otro para un char para verificar el alfabeto. El siguiente código ilustra esto:

#incluir
usando el espacio de nombres STD;
char entrada = '*';
int main ()

intentar

if (isDigit (entrada))
tirar 10;
if (isalpha (entrada))
arrojar 'z';

Catch (int)

cout << "Digit input is forbidden!" << '\n';

Catch (char)

cout << "Character input is forbidden!" << '\n';

regresar 0;

No hay salida. Si el valor de la entrada fuera un dígito, e.gramo., '1', la salida habría sido:

"La entrada de dígitos está prohibida!"

Si el valor de la entrada fuera un alfabeto, e.gramo., 'A', la salida habría sido:

"La entrada del personaje está prohibida!"

Tenga en cuenta que en la lista de parámetros de los dos bloqueos de captura, no hay nombre de identificador. También tenga en cuenta que en la definición de los dos bloques de captura, los argumentos particulares lanzados no se han verificado si sus valores son exactos o no.

Lo que importa para una captura es el tipo; una captura debe coincidir con el tipo de operando lanzado. El valor particular del argumento (operando) lanzado se puede utilizar para una verificación adicional si es necesario.

Más de un manejador para el mismo tipo

Es posible tener dos manejadores del mismo tipo. Cuando se lanza una excepción, el control se transfiere al controlador más cercano con un tipo de coincidencia. El siguiente programa ilustra esto:

#incluir
usando el espacio de nombres STD;
char entrada = '1';
int main ()

intentar

if (isDigit (entrada))
tirar 10;

Catch (int)

cout << "Digit input is forbidden!" << '\n';

Catch (int)

cout << "Not allowed at all: digit input!" << '\n';

regresar 0;

La salida es:

"La entrada de dígitos está prohibida!"

Bloques de prueba/captura anidados:

Los bloques de prueba/captura se pueden anidar. El programa anterior para la entrada de caracteres no alfanuméricos del teclado se repite aquí, pero con el código de error alfabético anidado:

#incluir
usando el espacio de nombres STD;
char entrada = '*';
int main ()

intentar

if (isDigit (entrada))
tirar 10;
intentar

if (isalpha (entrada))
arrojar 'z';

Catch (char)

cout << "Character input is forbidden!" << '\n';


Catch (int)

cout << "Digit input is forbidden!" << '\n';

regresar 0;

El error Alfabético TRY/Catch-Block está anidado en el bloque de try del código dígito. La operación de este programa y la operación anterior desde la que se copia es la misma.

Noxcept-especificador

Considere la siguiente función:

nulo fn (const char* str) noexcept

if (islower (str [0]))
tirar 'l';

Observe el especificador 'Noexcept' justo después del paréntesis correcto de la lista de parámetros de función. Esto significa que la función no debería lanzar una excepción. Si la función arroja una excepción, como en este caso, se compilará con un mensaje de advertencia pero no se ejecutará. Un intento de ejecutar el programa llamará a la función especial std :: terminado (), que debería detener el programa con gracia en lugar de permitir que se bloquee literalmente.

El especificador noexcept está en diferentes formas. Estos son los siguientes:

escriba func () noexcept; : no permite una expresión de lanzamiento
type func () noexcept (verdadero); : permite una expresión de lanzamiento
escriba func () throw (); : no permite una expresión de lanzamiento
escriba func () noexcept (falso); : permite una expresión de lanzamiento, que es opcional
escriba func (); : permite una expresión de lanzamiento, que es opcional

Verdadero o falso en los paréntesis puede ser reemplazado por una expresión que resulta en verdadero o falso.

La función especial std :: terminado ():

Si no se puede manejar una excepción, debe volver a publicar. En este caso, la expresión arrojada puede o no tener un operando. La función especial std :: termine () se llamará en tiempo de ejecución, que debería detener el programa con gracia en lugar de permitir que se bloquee literalmente.

Escriba, compile y ejecute el siguiente programa:

#incluir
usando el espacio de nombres STD;
char entrada = '1';
int main ()

intentar

if (isDigit (entrada))
tirar 10;

Catch (int)

tirar;

regresar 0;

Después de una compilación exitosa, el programa terminó sin ejecutarse, y el mensaje de error de la computadora del autor es:

"Terminar llamado después de lanzar una instancia de 'int'

Abortado (arrojado núcleo) "

Conclusión:

La función de excepción en C ++ evita que un segmento de código se ejecute en función de algún tipo de entrada. El programa continúa ejecutándose según sea necesario. La construcción de excepción (prevención de errores) consiste en un bloque de try y un bloque de captura. El bloque de try tiene el segmento de código de interés, que puede ser omitido, dependiendo de alguna condición de entrada. El bloque de try tiene la expresión de lanzamiento, que lanza un operando. Este operando también se llama la excepción. Si el tipo de operando y el tipo para el parámetro del bloque de captura son los mismos, entonces se atrapa la excepción (se maneja). Si la excepción no se atrapa, el programa se cancelará, pero aún así, esté seguro ya que el segmento de código que se ejecutaría para dar el resultado incorrecto no se ha ejecutado. El manejo de excepciones típicas significa pasar por alto el segmento de código y enviar un mensaje de error al usuario. El segmento de código se ejecuta para una entrada normal pero se pasa por alto para entradas incorrectas.