2012-02-27 18 views
25

Esto podría ser una pregunta tonta, pero en C++, cuando quiero lanzar una excepción ... ¿qué arrojo?¿Qué arrojar al lanzar excepciones de C++?

¿Se supone que debo lanzar std :: exception, o es eso reservado por la biblioteca estándar? ¿O debería lanzar una cadena o int? ¿O debería arrojar lo que sea que sea apropiado?

+3

¡No arroje cuerdas ni tuercas! Si siempre lanza subclases de 'std :: exception', puede poner una cláusula catch-all en' main' que maneja todas las excepciones que no se manejan en ninguna otra parte e imprime el 'what()' de la excepción. –

Respuesta

31

Lanzar una clase que se deriva de std::exception; si #include <stdexcept>, puede elegir entre un número de ready-made, useful clases derivadas.

Derivando de std::exception permite a sus manejadores seguir un estilo reconocible, ya que siempre puede usar .what() para obtener un mensaje de texto. No arroje tipos primitivos, ya que no llevan información semántica.

+10

Resumiría (aunque prácticamente lo mismo) que en la mayoría de los casos las personas deberían derivar sus excepciones de std :: runtime_error (que a su vez deriva de std :: exception) –

8

En general, las personas no lanzan std :: exception directamente por el simple motivo de que no almacena ningún mensaje de error. No habría nada para qué método regresar. A veces me confundo porque MSVC proporciona una extensión no estándar para este constructor parametrizado en std :: exception que acepta una cadena.

Puede elegir entre las clases de excepción existentes como std :: runtime_exception o definir la suya propia. Esto es algo subjetivo, pero recomiendo mantener el número de clases de excepción al mínimo ya que RAII puede eliminar la necesidad de tener múltiples ramas de código y atrapar bloques para diferentes tipos de excepciones. A menudo, el mensaje combinado con el código conforme con RAII es suficiente para recuperarse con gracia de cualquier excepción.

Y, por último, recomiendo todas las excepciones arrojadas heredar de std :: exception por razones similares. No quiere tener que ensuciar su código con muchos bloques de captura diferentes para diferentes tipos de excepciones si puede evitarlo. Resuelve el problema tan generalmente como puedas.

+1

¿No quiere decir 'std :: runtime_error'? –

1

A diferencia de Java, puede arrojar lo que desee (int, string, MyClass, ...). Pero escucha a Kerrek. :)

0

Normalmente querrá lanzar una de las excepciones derivadas de std::exception como han dicho otros.

En ocasiones he lanzado otros tipos, pero solo si está atrapado dentro del mismo bloque y el valor es algo útil en ese contexto.

+0

Si está atrapando "dentro del mismo bloque", probablemente no debería lanzar una excepción en primer lugar. Las excepciones son para condiciones excepcionales, pero si puede manejar la condición allí mismo, parece que es solo parte del flujo normal del programa. (Y no olvide que * tirar * una excepción puede ser mucho más costoso que simplemente consultar un estado local.) –

+0

@KerrekSB, no recuerdo las circunstancias exactas en las que lo hice, pero estoy seguro de que era una condición excepcional que no era parte del flujo * normal *. Probablemente también anidado profundamente donde los enfoques alternativos hubieran sido más feos. –

+2

Bastante justo. Hay * situaciones * donde una excepción puede hacer que un algoritmo complicado sea más claro y fácil de entender ... –

2

La principal excepción para arrojar algo derivado de std::exception sería si está utilizando algún marco (por ejemplo, MFC) con su propia jerarquía de excepciones. En ese caso, generalmente desea derivar de un lugar apropiado en su jerarquía.

Tenga en cuenta que no estoy intentando especialmente mantener MFC como un ejemplo de manejo limpio de excepciones (o diseño limpio en general), solo un ejemplo de un marco que incluye una jerarquía de excepciones. Cuando usa un marco que ya define una jerarquía de excepciones, generalmente es mejor usarlo.

En otras palabras, a diferencia de la preferencia en C++ de lo contrario, generalmente se acepta que las excepciones deben ser una única jerarquía monolítica con una sola raíz. Para la biblioteca estándar, esa única raíz es std::exception, pero otros marcos tienen alternativas, y si proporcionan una, generalmente quiere que la suya sea la suya.

Cuestiones relacionadas