¿Cuál es la diferencia entre std::runtime_error
y std::exception
? ¿Cuál es el uso apropiado para cada uno? ¿Por qué son diferentes en primer lugar?
fuente
¿Cuál es la diferencia entre std::runtime_error
y std::exception
? ¿Cuál es el uso apropiado para cada uno? ¿Por qué son diferentes en primer lugar?
std::exception
es la clase cuyo único propósito es servir como la clase base en la jerarquía de excepciones. No tiene otros usos. En otras palabras, conceptualmente es una clase abstracta (aunque no se define como clase abstracta en el significado C ++ del término).
std::runtime_error
es una clase más especializada, descendente std::exception
, destinada a ser lanzada en caso de varios errores de tiempo de ejecución . Tiene un doble propósito. Se puede lanzar por sí mismo, o puede servir como una clase base para varios tipos aún más especializados de excepciones de errores de tiempo de ejecución, como std::range_error
, std::overflow_error
etc. Puede definir sus propias clases de excepción que descienden std::runtime_error
, así como también puede definir su propia excepción clases descendientes de std::exception
.
Al igual que std::runtime_error
, la biblioteca estándar contiene std::logic_error
, también descendiendo de std::exception
.
El punto de tener esta jerarquía es dar al usuario la oportunidad de usar toda la potencia del mecanismo de manejo de excepciones de C ++. Dado que la cláusula 'catch' puede capturar excepciones polimórficas, el usuario puede escribir cláusulas 'catch' que pueden capturar tipos de excepción de un subárbol específico de la jerarquía de excepciones. Por ejemplo, catch (std::runtime_error& e)
capturará todas las excepciones del std::runtime_error
subárbol, permitiendo que todos los demás pasen (y vuelen más arriba en la pila de llamadas).
PD: Diseñar una jerarquía de clases de excepción útil (que le permita detectar solo los tipos de excepción que le interesan en cada punto de su código) es una tarea no trivial. Lo que ve en la biblioteca estándar de C ++ es un enfoque posible, ofrecido por los autores del lenguaje. Como puede ver, decidieron dividir todos los tipos de excepción en "errores de tiempo de ejecución" y "errores lógicos" y le permitieron continuar desde allí con sus propios tipos de excepción. Por supuesto, hay formas alternativas de estructurar esa jerarquía, que podrían ser más apropiadas en su diseño.
Actualización: Portabilidad Linux vs Windows
Como Loki Astari y unixman83 señalaron en su respuesta y comentarios a continuación, el constructor de la exception
clase no toma ningún argumento de acuerdo con el estándar C ++. Microsoft C ++ tiene un constructor que toma argumentos en la exception
clase, pero esto no es estándar. La runtime_error
clase tiene un constructor que toma argumentos ( char*
) en ambas plataformas, Windows y Linux. Para ser portátil, mejor uso runtime_error
.
(Y recuerde, solo porque una especificación de su proyecto dice que su código no tiene que ejecutarse en Linux, no significa que nunca tenga que ejecutarse en Linux).
std::exception
. Claro, todas lasstd
cosas arrojan clases derivadas de eso, pero no hay absolutamente ninguna razón para lanzar solostd::exception
objetos derivados.std::exception
debe considerarse (tenga en cuenta lo considerado) la base abstracta de la jerarquía de excepción estándar. Esto se debe a que no existe un mecanismo para pasar un mensaje específico (para hacerlo, debe derivar y especializarsewhat()
). No hay nada que le impida usar std :: exception y para aplicaciones simples puede ser todo lo que necesita.std::runtime_error
por otro lado tiene constructores válidos que aceptan una cadena como mensaje. Cuandowhat()
se llama, se devuelve un puntero const char que apunta a una cadena C que tiene la misma cadena que se pasó al constructor.fuente
std::exception(std::string)
. Ahora me doy cuenta de que debo tirarstd::runtime_error
si quiero que mi código funcione en Linux (GCC).