try - ¿Por qué las compilaciones no controlan las excepciones en C++?
try catch ejemplo (6)
Echa un vistazo a esto:
http://www.gotw.ca/publications/mill22.htm
básicamente, las especificaciones de excepción no son viables / inutilizables, pero eso no hace que las excepciones sean inviables.
En cuanto a su pregunta, no hay forma de que el compilador compruebe que cada tipo arrojado está atrapado en algún lugar más alto en el código, espero que las unidades de compilación dificulten esto y es imposible hacerlo para el código destinado a ser utilizado en una biblioteca ( donde el nivel superior no está disponible en el momento de la compilación). Si quieres estar seguro de que todo está atrapado, pega una trampa (...) en la parte superior de tu código.
C ++ proporciona una sintaxis para las excepciones marcadas, por ejemplo:
void G() throw(Exception);
void f() throw();
Sin embargo, el compilador de Visual C ++ no los comprueba; la bandera de tiro simplemente se ignora. En mi opinión, esto hace que la característica de excepción no se pueda usar. Entonces mi pregunta es: ¿hay alguna manera de que el compilador verifique si las excepciones se capturan / vuelven a lanzar correctamente? Por ejemplo, un complemento de Visual C ++ o un compilador de C ++ diferente.
PD. Quiero que el compilador compruebe si las excepciones están correctamente capturadas, de lo contrario terminarás en una situación en la que tienes que poner un freno a cada llamada de función que hagas, incluso si explícitamente afirman que no arrojarán nada .
Actualización: el compilador de Visual C ++ muestra una advertencia al lanzar una función marcada con throw (). Esto es genial, pero lamentablemente, la advertencia no aparece cuando llamas a una subrutina que podría arrojar. Por ejemplo:
void f() throw(int) { throw int(13); }
void h() throw() { g(); } //no warning here!
Las especificaciones de excepción son bastante inútiles en C ++.
No se aplica que no se lanzarán otras excepciones, sino simplemente que se llamará a la función global unexpected()
(que se puede establecer)
El uso de especificaciones de excepción se reduce a engañarse a sí mismo (oa sus pares) con una falsa sensación de seguridad. Mejor simplemente no molestarse.
Lo curioso es que Java ha verificado las excepciones, y los programadores de Java también las odian.
Las especificaciones de excepción en C ++ son inútiles por 3 razones:
1. Las especificaciones de excepción de C ++ inhiben la optimización.
Con la excepción, posiblemente, de throw (), los compiladores insertan código adicional para verificar que cuando se lanza una excepción, coincida con la especificación de excepción de funciones durante un desenrollado de la pila. Manera de hacer que tu programa sea más lento.
2. Las especificaciones de excepción de C ++ no son implementadas por el compilador
En lo que respecta a su compilador, lo siguiente es sintácticamente correcto:
void AStupidFunction() throw()
{
throw 42;
}
Lo que es peor, nada útil sucede si viola una especificación de excepción. ¡Tu programa simplemente termina!
3. Las especificaciones de excepción de C ++ son parte de la firma de una función.
Si tiene una clase base con una función virtual e intenta sobrescribirla, las especificaciones de excepción deben coincidir exactamente. Por lo tanto, será mejor que planees con anticipación, y sigue siendo un dolor.
struct A
{
virtual int value() const throw() {return 10;}
}
struct B : public A
{
virtual int value() const {return functionThatCanThrow();} // ERROR!
}
Las especificaciones de excepción le dan estos problemas, y la ganancia para usarlos es mínima. Por el contrario, si evita por completo las especificaciones de excepción, la codificación es más fácil y evita estas cosas.
No puedo verificar esto por falta de una instalación de MSVC, pero ¿está seguro de que el compilador ignora la especificación throw ()?
Esta página de MSDN sugiere que Microsoft conoce throw () y espera que su compilador lo maneje correctamente. Bueno, casi, vea la nota sobre cómo se apartan del estándar ANSI / ISO en algunos detalles.
Editar: en la práctica, sin embargo, estoy de acuerdo con Patrick: las especificaciones de excepción son en su mayoría inútiles.
Para detectar casos anteriores al tiempo de ejecución, como ...
extern void f() throw (class Mystery);
void g() throw() {
f() ;
}
... necesitas análisis estático Sí, el compilador está haciendo un montón de análisis estático, pero porque el estándar es "raise std :: unexpected si el lanzamiento no coincide", y es perfectamente legal escribir una rutina que arroje un objeto que no coincida con el especificador. , los implementadores del compilador ni advierten ni comentan.
Las herramientas de análisis estático que pretenden proporcionar un servicio de advertencia incluyen la pelusa de Gimpel Software para C ++ ...
1560 Excepción no detectada ''Nombre'' no está en lista de lanzamiento para la función ''Símbolo''
y, según esta respuesta a una pregunta anterior, QA C ++ .
Porque el estándar así lo dice. La declaración de excepción no significa que no se lanzará ninguna otra excepción. Significa que si se lanza una excepción no declarada, se llamará una función global especial llamada inesperada () , que por defecto termina el programa. Generalmente se desaconseja declarar excepciones en las funciones (tal vez excepto en la lista de excepciones vacías) ya que el comportamiento estándar no es muy útil.