c++ - son - try catch en c
¿El manejo de excepciones requiere programación orientada a objetos? (9)
En este punto de mi experiencia de programación, me doy cuenta de lo mal que estoy por tener el manejo de excepciones disponible en la mayoría de los lenguajes que se usan hoy en día (C ++, .Net, Java, etc.), al menos en comparación con C. Me estoy preparando para tomar una Curso avanzado de C y me hace pensar realmente esos términos en comparación con mi paradigma actual.
En C, depende del programador evitar que se produzcan errores en primer lugar, lo que es bastante desalentador para cualquiera que esté acostumbrado al manejo de excepciones. Me ha ocurrido que cualquier lenguaje con el que me haya topado y que tenga un manejo de excepciones esté orientado a objetos. El primer lenguaje orientado a objetos para tener manejo de excepciones, al menos que yo sepa, es C ++, que es una especie de evolución de C. (corríjame si me equivoco)
Dicho esto, ¿hay algo acerca de la naturaleza orientada a objetos de un lenguaje que permite el manejo de excepciones, o se agregó el manejo de excepciones como una característica ya que los lenguajes orientados a objetos realmente comenzaron a convertirse en un lugar común? ¿Qué es lo que a C le falta para decir, C ++, en el código de máquina que hace que el trabajo de excpetion?
Encontré esta post sobre cómo funciona el manejo de excepciones bajo el capó, pero no estoy segura de cómo se aplica esa información a mi pregunta ( es decir, ¿a C no le quedan notificaciones, continuaciones, etc.? ). Gracias por adelantado.
¿El manejo de excepciones requiere programación orientada a objetos?
No. Los dos están completamente separados. Uno puede tener idiomas OO que no tienen el manejo de excepciones como una primitiva de flujo de control, y uno puede tener un manejo de excepciones en idiomas que no son OO.
La programación orientada a objetos, tal como lo señala Wikipedia, es un estilo de programación que enfatiza el valor de la abstracción , la encapsulación , la mensajería , la modularidad , el polimorfismo y la herencia para lograr la reutilización de códigos de bajo costo y la administración efectiva de software complejo. Proyectos implementados por grandes equipos.
No ve "bucles" o "declaraciones if" o "goto" o "try-catch-finally-throw" en esa lista porque las primitivas de flujo de control no tienen nada que ver con la abstracción, encapsulación, mensajería, modularidad, polimorfismo o la herencia se utiliza para lograr la reutilización de código de bajo costo o la gestión eficaz de proyectos de software complejos por parte de grandes equipos.
¿Qué es lo que C no tiene para decir, C ++, en el código de máquina que hace que las excepciones funcionen?
Es cierto que el hardware moderno está diseñado con un manejo excepcional como una primitiva de flujo de control en mente. C se diseñó mucho antes de que existiera el hardware moderno, lo que haría más difícil la implementación del manejo de excepciones en C que se ejecuta de manera eficiente en todo el hardware en el que C se ejecuta.
Pero dicho eso, no hay nada que le impida a usted ni a nadie más diseñar una nueva versión de C que tenga un manejo de excepciones como una primitiva de flujo de control, pero sin todas las demás características de C ++.
Si está interesado en el tema de cómo agregar el manejo de excepciones a los idiomas que no son OO que admiten continuaciones, vea mi artículo sobre el tema que esboza la idea:
¿El manejo de excepciones requiere programación orientada a objetos?
No. Los dos son ortogonales. Otros mencionaron el setjmp
y el longjmp
usados en C para manejar los errores. Quiero mencionar a SEH.
SEH (manejo de excepciones estructuradas) es una extensión de Microsoft a C con un soporte de nivel de sistema operativo. Te permite escribir código como ( ejemplo de MSDN ):
__try
{
*pResult = dividend / divisor;
}
__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// handle exception
}
También puede aumentar sus propias excepciones llamando a RaiseException
. A diferencia de setjmp
y longjmp
, puedes hacer tu propia limpieza en __finally
bloques. De hecho, las excepciones de C ++ se implementan sobre SEH (en Windows).
Este es un ejemplo de manejo de excepciones en forma totalmente no orientada a objetos.
Otro ejemplo en C ++ que no usa ninguna característica orientada a objetos:
try {
throw "Boom!";
} catch(const char* str) {
printf("Error: %s/n", str);
}
Dicho esto, ¿hay algo acerca de la naturaleza orientada a objetos de un lenguaje que permite el manejo de excepciones, o se agregó el manejo de excepciones como una característica ya que los lenguajes orientados a objetos realmente comenzaron a convertirse en un lugar común?
La primera vez que llegué a conocer excepciones fue cuando tuve que aprender Ada (estudiando CS) a principios de los 90. IIRC, Ada tenía un tipo especial de Exception
. En aquel entonces, no era un lenguaje orientado a objetos. (Ada95 agregó algunos conceptos de OO). Sin embargo, estoy de acuerdo en que el desenrollado de la pila (es decir, la limpieza automática completa de los recursos asignados) es un rasgo importante para el éxito del manejo de excepciones. La combinación de destructores con el manejo de excepciones es un punto importante para el éxito de las excepciones en C ++.
También me parece recordar que Stroustrup mencionó a Ada como una gran influencia para el manejo de excepciones en C ++.
Bueno, las excepciones se encuentran dentro del lenguaje ensamblador, donde puede usar trampas (excepción forzada) y otras excepciones para controlar el flujo del programa. Un ejemplo sería un puntero nulo o por qué no . No hay nada sobre la naturaleza de los lenguajes OO que permita el manejo de excepciones. Simplemente lo hacen más fácil (y los lenguajes de alto nivel tienen una tendencia a lanzar muchas más excepciones). Las excepciones son una característica clave en la programación básica. Y con eso no me refiero a toda la programación, me refiero a la programación "regular", incluido el ensamblaje. No entiendo a qué se refiere cuando dice "¿qué es lo que a C le falta para decir, C ++, en el código de máquina que hace que las excepciones funcionen?". Y no diría que depende completamente del programador detectar excepciones en C (pero soy un novato en esta área. Si alguien puede corregirme, hágalo).
El manejo de excepciones ha existido durante bastante tiempo, mucho antes de C ++. Varios idiomas "boutique" implementaron el manejo de excepciones bastante pronto, pero Ada (finales de los 70, IIRC) fue probablemente el más conocido. Ada tenía destellos de OO-ness, pero no era OO por ningún estándar moderno.
El manejo de excepciones también se implementó en varias versiones de los lenguajes PL / S (definitivamente no OO) que se utilizaron principalmente de forma interna para IBM. Las implementaciones tempranas (que se remontan a finales de los 70) se desarrollaron utilizando macros (el procesador de macros PS / S era superior a la mayoría desde entonces), pero las versiones posteriores incorporaron EH en el lenguaje.
Los lenguajes no orientados a objetos que implementan el manejo de excepciones incluyen:
- SU TECO
- PL / 1 (Multics)
- C (como varias personas han señalado, a través de
setjmp
/longjmp
) - C por medio de señales Unix: las señales del kernel Unix se derivan de la facilidad de manejo de excepciones de Multics
- versiones anteriores de Lisp (concedidas, Common Lisp permite OOP, pero no cuando se agregaron las condiciones y los reinicios) que aparentemente implementaron las condiciones y los reinicios (
unwind-protect
) de ITS TECO - de acuerdo con RMS (http: // www. gsim.aoyama.ac.jp/~ida/GNU/RMStalk1207.html), lo que implica que Lisp realmente heredó el manejo de excepciones por medio de Emacs (¡ingenioso!)
Para un ejemplo no imperativo, intente Haskell para el tamaño. Las excepciones ni siquiera tienen que estar integradas en el lenguaje; son solo parte del tipo de devolución (por ejemplo, Either MyException MyValue
o ExceptionalT IOException IO String
). Las excepciones estándar se pueden manejar con la función try
del módulo Control.Exception
:
main = do
result <- try (evaluate (1 `div` 0))
case result of
Left exception -> putStrLn $ "Caught: " ++ show exception
Right value -> putStrLn $ "Result: " ++ show value
También puede usar una función como un controlador de excepciones con la función catch
, aquí se usa infijo:
main = (print $ 1 `div` 0) `catch` /exception ->
putStrLn $ "Caught: " ++ show exception
Y puede utilizar la mónada de excepción para realizar operaciones de lanzamiento de excepciones en otra mónada. Al manejar todas las excepciones posibles, se escapa de la mónada Excepción.
main =
do result <- runExceptionalT someFunction
case result of
Exception exception -> putStrLn ("Caught: " ++ show exception)
Success value -> putStrLn ("Result: " ++ show value)
Debido a que una excepción forma parte de la firma de tipo de una función, debe ser explicada explícitamente. Esto es esencialmente lo mismo que las excepciones comprobadas en Java.
C no carece de nada en el código de máquina, y el manejo de excepciones fue y es común en C con setjmp
y longjmp
.
El motivo de la falta completa de una función de nivel de idioma en lenguajes puramente procedimentales es que el manejo de excepciones es idéntico a setjmp
cuando no es necesario llamar a los destructores. El manejo de excepciones ha existido antes en lenguajes exóticos, pero nunca se prendió porque era un azúcar puramente sintáctico. Sin embargo, una vez que los destructores entraron en escena y se hizo necesario el desenrollado de la pila , el soporte a nivel del idioma se hizo necesario y el manejo de excepciones se implementó ampliamente como parte del lenguaje.