2009-10-15 25 views

Respuesta

129

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 C++, significado del término).

std::runtime_error es una clase más especializada, que desciende de std::exception, destinado a ser lanzado en el caso de varios tiempo de ejecución errores. Tiene un doble propósito. Se puede lanzar solo, o puede servir como una clase base para varios tipos más especializados de excepciones de error en tiempo de ejecución, como std::range_error, std::overflow_error, etc. Puede definir sus propias clases de excepciones descendientes desde std::runtime_error, así como también puede definir sus propias clases de excepciones que descienden de std::exception.

Al igual que std::runtime_error, la biblioteca estándar contiene std::logic_error, también desciende de std::exception.

El objetivo de tener esta jerarquía es dar al usuario la oportunidad de utilizar todo el poder del mecanismo de manejo de excepciones de C++. Como 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) captará todas las excepciones desde el subárbol std::runtime_error, permitiendo que todos los demás pasen (y vuelen más arriba en la pila de llamadas).

P.S. Diseñar una jerarquía útil de clases de excepción (que le permita capturar solo los tipos de excepción que le interesan en cada punto de su código) es una tarea no trivial. Lo que se 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 de lógica" y le permiten continuar desde allí con sus propios tipos de excepciones. Existen, por supuesto, formas alternativas de estructurar esa jerarquía, que podría ser más apropiada en su diseño.

Actualización: Portabilidad de Windows Linux vs

Como Loki Astari y unixman83 señaló en su respuesta y comentarios a continuación, el constructor de la clase exception no toma ningún argumento según el estándar C++. Microsoft C++ tiene un constructor tomando argumentos en la clase exception, pero esto no es estándar. La clase runtime_error tiene un constructor tomando argumentos (char*) en ambas plataformas, Windows y Linux. Para ser portátil, mejor uso runtime_error.

(Y recuerde, sólo porque una especificación de su proyecto dice su código no tiene que ejecutar en Linux, esto no significa que no nunca se tiene que ejecutar en Linux.)

+0

gracias. gran respuesta. aunque me pregunto si alguna vez existe la necesidad de tener un tipo diferente de excepción ... solo un pensamiento. – sivabudh

+0

Si hay una posibilidad de que se pueda volver a cubrir la excepción, entonces puede ser útil un tipo diferente de excepción, ya que podemos usar el mecanismo de manejo de excepciones para dirigir la excepción al controlador que intentará corregir el problema. Si no hay posibilidad de recuperación, una de las excepciones estándar está bien. –

+1

Solo como un lado: no hay ninguna regla, en ninguna parte, que te obligue a derivar de 'std :: exception'. Claro, todas las cosas 'std' arrojan clases derivadas de eso, pero no hay absolutamente ninguna razón para lanzar solo objetos derivados' std :: exception'. – rubenvb

15

std :: excepción debe ser considera (tenga en cuenta lo considerado) la base abstracta de la jerarquía de excepción estándar. Esto se debe a que no hay un mecanismo para pasar en un mensaje específico (para hacerlo debe derivar y especializar qué()). No hay nada que le impida usar std :: exception y para aplicaciones simples puede ser todo lo que necesita.

std :: runtime_error por el contrario tiene constructores válidos que aceptan una cadena como un mensaje.Cuando lo que() se llama un puntero const char se devuelve que apunta a una cadena C que tiene la misma cadena que se pasó al constructor.

try 
{ 
    if (badThingHappened) 
    { 
     throw std::runtime_error("Something Bad happened here"); 
    } 
} 
catch(std::exception const& e) 
{ 
    std::cout << "Exception: " << e.what() << "\n"; 
} 
+1

Gracias por la respuesta Martin. Sin embargo, uso std :: exception() de la misma manera que describiste arriba. es decir, el constructor std :: exception() también puede tomar std :: string() o const char *. – sivabudh

+12

No según el estándar. std :: exception tiene un constructor que no toma argumentos. Usar una versión que acepte std :: string o C-String no es portátil. –

+7

Debido a Microsoft, me acostumbré a lanzar 'std :: exception (std :: string)'. Ahora me doy cuenta de que debo lanzar 'std :: runtime_error' si quiero que mi código funcione en Linux (GCC). – unixman83

Cuestiones relacionadas