Lo que parece que estás atrapado es el infierno específico de alguien que intenta tener su pastel y comérselo también.
RAII y las excepciones están diseñadas para ir de la mano. RAII es el medio por el cual usted no tiene tener para escribir muchas declaraciones catch(...)
para realizar la limpieza. Ocurrirá automáticamente, como cuestión de rutina. Y las excepciones son la única forma de trabajar con objetos RAII, porque los constructores solo pueden tener éxito o lanzar (o poner el objeto en un estado de error, pero ¿quién quiere eso?).
Una declaración catch
puede hacer una de dos cosas: manejar un error o circunstancia excepcional, o hacer un trabajo de limpieza. A veces hace ambas cosas, pero cada declaración catch
existe para hacer al menos una de estas.
catch(...)
es incapaz de realizar el manejo adecuado de excepciones. No sabes cuál es la excepción; No puede obtener información sobre la excepción. No tiene absolutamente ninguna información más que el hecho de que algo haya lanzado una excepción dentro de un bloque de código determinado. Lo único legítimo que puedes hacer en un bloque así es hacer la limpieza. Y eso significa volver a lanzar la excepción al final de la limpieza.
Lo que le da RAII con respecto al manejo de excepciones es una limpieza gratuita. Si todo está encapsulado en RAII correctamente, entonces todo se limpiará correctamente. Ya no es necesario tener catch
de instrucciones para realizar la limpieza. En cuyo caso, no hay razón para escribir una declaración catch(...)
.
Entonces, estoy de acuerdo en que catch(...)
es mayormente malo ... provisionalmente .
Esa disposición es el uso adecuado de RAII. Porque sin ella, necesitas para poder realizar cierta limpieza. No hay manera de evitarlo; Tienes que ser capaz de hacer trabajos de limpieza. Debe poder asegurarse de que lanzar una excepción deje el código en un estado razonable. Y catch(...)
es una herramienta vital al hacerlo.
No puedes tener uno sin el otro. No puedes decir que tanto RAII como catch(...)
son malos. Necesitas al menos uno de estos; de lo contrario, no es una excepción segura.
Por supuesto, hay un uso válido aunque raro de catch(...)
que ni siquiera RAII puede eliminar: obtener un exception_ptr
para reenviarlo a otra persona. Por lo general, a través de una interfaz promise/future
o similar.
Mis compañeros de trabajo dicen que siempre debes saber qué excepciones se deben lanzar y que siempre puedes usar construcciones como:
Tu compañero de trabajo es un idiota (o simplemente terriblemente ignorante). Esto debería ser inmediatamente obvio debido a la cantidad de código de copiar y pegar que sugiere que escribas. La limpieza para cada una de esas declaraciones de captura será exactamente igual . Eso es una pesadilla de mantenimiento, sin mencionar la legibilidad.
En resumen: este es el problema que RAII se creó para resolver (no es que no resuelva otros problemas).
Lo que me confunde de esta noción es que generalmente se trata de cómo la mayoría de las personas argumentan que el RAII es malo. En general, el argumento es que "RAII es malo porque tienes que usar excepciones para señalar el fallo del constructor. Pero no puedes lanzar excepciones, porque no es seguro y tendrás que tener muchas declaraciones catch
para limpiar todo". " Que es un argumento roto porque RAII resuelve el problema que crea la falta de RAII.
Lo más probable es que esté en contra de RAII porque oculta los detalles. Las llamadas a los destructores no son visibles inmediatamente en las variables automáticas. Entonces obtienes código que es llamado implícitamente. Algunos programadores realmente odian eso. Aparentemente, hasta el punto en el que piensan que tener un 3% de declaraciones de catch
, todas las cuales hacen lo mismo con el código de copiar y pegar es una mejor idea.