Dominando el Manejo de Excepciones en C++: Guía Completa
Una excepción es un problema que surge durante la ejecución de un programa. Una excepción de C++ es una respuesta a una circunstancia excepcional que surge mientras un programa se está ejecutando, como un intento de dividir por cero.
Las excepciones proporcionan una forma de transferir control de una parte de un programa a otra. El manejo de excepciones en C++ se basa en tres palabras clave: try, catch y throw.
throw: Un programa lanza una excepción cuando surge un problema. Esto se hace usando la palabra clave throw.
catch: Un programa captura una excepción con un manejador de excepciones en el lugar del programa donde quieres manejar el problema. La palabra clave catch indica la captura de una excepción.
try: Un bloque try identifica un bloque de código para el cual excepciones particulares serán activadas. Es seguido por uno o más bloques catch.
Asumiendo que un bloque lanzará una excepción, un método captura una excepción usando una combinación de las palabras clave try y catch. Un bloque try/catch se coloca alrededor del código que podría generar una excepción. El código dentro de un bloque try/catch se refiere como código protegido, y la sintaxis para usar try/catch es la siguiente:
try {
// código protegido
} catch(ExceptionName e1) {
// bloque catch
} catch(ExceptionName e2) {
// bloque catch
} catch(ExceptionName eN) {
// bloque catch
}
Puedes listar múltiples declaraciones catch para capturar diferentes tipos de excepciones en caso de que tu bloque try lance más de una excepción en diferentes situaciones.
Lanzando Excepciones
Las excepciones pueden ser lanzadas en cualquier lugar dentro de un bloque de código usando la declaración throw. El operando de la declaración throw determina un tipo para la excepción y puede ser cualquier expresión y el tipo del resultado de la expresión determina el tipo de excepción lanzada.
El siguiente es un ejemplo de lanzar una excepción cuando ocurre una condición de división por cero:
double division(int a, int b) {
if(b == 0) {
throw "Condición de división por cero!";
}
return (a/b);
}
Capturando Excepciones
El bloque catch siguiente al bloque try captura cualquier excepción. Puedes especificar qué tipo de excepción quieres capturar y esto se determina por la declaración de excepción que aparece entre paréntesis siguiendo la palabra clave catch.
try {
// código protegido
} catch(ExceptionName e) {
// código para manejar excepción ExceptionName
}
El código anterior capturará una excepción de tipo ExceptionName. Si quieres especificar que un bloque catch debe manejar cualquier tipo de excepción que se lance en un bloque try, debes poner una elipsis, ..., entre los paréntesis que encierran la declaración de excepción de la siguiente manera:
try {
// código protegido
} catch(...) {
// código para manejar cualquier excepción
}
El siguiente es un ejemplo, que lanza una excepción de división por cero y la capturamos en el bloque catch.
#include <iostream>
using namespace std;
double division(int a, int b) {
if(b == 0) {
throw "Condición de división por cero!";
}
return (a/b);
}
int main() {
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
} catch(const char* msg) {
cerr << msg << endl;
}
return 0;
}
Debido a que estamos lanzando una excepción de tipo const char*, al capturar esta excepción, tenemos que usar const char* en el bloque catch. Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado:
Condición de división por cero!
Excepciones Estándar de C++
C++ proporciona una lista de excepciones estándar definidas en <exception> que podemos usar en nuestros programas. Estas están organizadas en una jerarquía de clases padre-hijo mostrada a continuación:

Aquí está la pequeña descripción de cada excepción mencionada en la jerarquía anterior:
| Nº | Excepción y Descripción |
|---|---|
| 1 | std::exception Una excepción y clase padre de todas las excepciones estándar de C++. |
| 2 | std::bad_alloc Esto puede ser lanzado por new. |
| 3 | std::bad_cast Esto puede ser lanzado por dynamic_cast. |
| 4 | std::bad_exception Este es un dispositivo útil para manejar excepciones inesperadas en un programa C++. |
| 5 | std::bad_typeid Esto puede ser lanzado por typeid. |
| 6 | std::logic_error Una excepción que teóricamente puede ser detectada leyendo el código. |
| 7 | std::domain_error Esta es una excepción lanzada cuando se usa un dominio matemáticamente inválido. |
| 8 | std::invalid_argument Esto se lanza debido a argumentos inválidos. |
| 9 | std::length_error Esto se lanza cuando se crea un std::string demasiado grande. |
| 10 | std::out_of_range Esto puede ser lanzado por el método 'at', por ejemplo un std::vector y std::bitset<>::operator[](). |
| 11 | std::runtime_error Una excepción que teóricamente no puede ser detectada leyendo el código. |
| 12 | std::overflow_error Esto se lanza si ocurre un desbordamiento matemático. |
| 13 | std::range_error Esto ocurre cuando intentas almacenar un valor que está fuera de rango. |
| 14 | std::underflow_error Esto se lanza si ocurre un subdesbordamiento matemático. |
Definir Nuevas Excepciones
Puedes definir tus propias excepciones heredando y sobrescribiendo la funcionalidad de la clase exception. El siguiente es un ejemplo, que muestra cómo puedes usar la clase std::exception para implementar tu propia excepción de manera estándar:
#include <iostream>
#include <exception>
using namespace std;
struct MiExcepcion : public exception {
const char* what() const throw() {
return "Excepción C++";
}
};
int main() {
try {
throw MiExcepcion();
} catch(MiExcepcion& e) {
std::cout << "MiExcepcion capturada" << std::endl;
std::cout << e.what() << std::endl;
} catch(std::exception& e) {
// Otros errores
}
}
Esto produciría el siguiente resultado:
MiExcepcion capturada
Excepción C++
Aquí, what() es un método público proporcionado por la clase exception y ha sido sobrescrito por todas las clases hijas de excepciones. Esto retorna la causa de una excepción.
Lenguaje C
- Dominando los Operadores en C++: Guía Completa con Ejemplos Prácticos
- Comentarios en C++: Mejores Prácticas para Código Legible y Mantenible
- Dominando las plantillas de clase en C++: guía práctica
- Manejo de archivos en C: Dominando E/S con fopen, fprintf, fread y fseek
- Manejo de excepciones en C++: Guía práctica con try, catch, throw
- Manejo de Errores en C: Mejores Prácticas y Técnicas
- Lenguaje de Programación C++: Visión General y Características Clave
- Constantes y Literales en C++: Tipos, Sintaxis y Mejores Prácticas
- Guía Completa de Operadores en C++: Tipos, Uso y Mejores Prácticas
- Dominando el manejo de excepciones en Python: try, except, finally y raise efectivamente
- Dominando el manejo de excepciones en Java: Try, Catch, Finally, Throw y Throws explicados