Was Sie gefangen zu sein scheinen, ist die Hölle, in der jemand versucht, seinen Kuchen zu haben und ihn auch zu essen.
RAII und Ausnahmen sollen Hand in Hand gehen. RAII ist das Mittel, mit dem Sie nicht viele Anweisungen schreiben müssen , um catch(...)
aufzuräumen. Dies geschieht selbstverständlich automatisch. Und Ausnahmen sind die einzige Möglichkeit, mit RAII-Objekten zu arbeiten, da Konstruktoren nur erfolgreich sein oder werfen können (oder das Objekt in einen Fehlerzustand versetzen können, aber wer will das?).
Eine catch
Anweisung kann eine der beiden folgenden Aufgaben ausführen: Fehler oder außergewöhnliche Umstände behandeln oder Aufräumarbeiten ausführen. Manchmal macht es beides, aber es gibt jede catch
Anweisung, um mindestens eine davon zu tun.
catch(...)
kann keine ordnungsgemäße Ausnahmebehandlung durchführen. Sie wissen nicht, was die Ausnahme ist. Sie können keine Informationen über die Ausnahme erhalten. Sie haben absolut keine andere Information als die Tatsache, dass eine Ausnahme von etwas in einem bestimmten Codeblock ausgelöst wurde . Das einzig legitime, was Sie in einem solchen Block tun können, ist aufzuräumen. Und das bedeutet, die Ausnahme am Ende der Bereinigung erneut auszulösen.
Was RAII Ihnen in Bezug auf die Ausnahmebehandlung bietet, ist die kostenlose Bereinigung. Wenn alles ordnungsgemäß in RAII eingekapselt ist, wird alles ordnungsgemäß bereinigt. catch
Anweisungen müssen nicht mehr bereinigt werden. In diesem Fall gibt es keinen Grund, eine catch(...)
Erklärung abzugeben.
Also würde ich zustimmen, dass catch(...)
das meistens böse ist ... vorläufig .
Diese Bestimmung ist die ordnungsgemäße Verwendung von RAII. Denn ohne sie, Sie müssen bestimmte Bereinigungen tun zu können. Daran führt kein Weg vorbei. Sie müssen in der Lage sein, Aufräumarbeiten zu erledigen. Sie müssen sicherstellen können, dass durch das Auslösen einer Ausnahme der Code in einem angemessenen Zustand bleibt. Und catch(...)
ist dabei ein wichtiges Instrument.
Sie können nicht eins ohne das andere haben. Man kann nicht sagen, dass sowohl RAII als catch(...)
auch schlecht sind. Sie benötigen mindestens eines davon. Andernfalls sind Sie nicht ausnahmesicher.
Natürlich gibt es eine gültige, wenn auch seltene Verwendung catch(...)
, die nicht einmal RAII verbannen kann: die exception_ptr
Weiterleitung an eine andere Person. In der Regel über eine promise/future
oder eine ähnliche Schnittstelle.
Meine Kollegen sagen, dass Sie immer wissen sollten, welche Ausnahmen geworfen werden sollen und dass Sie immer Konstrukte verwenden können wie:
Ihr Mitarbeiter ist ein Idiot (oder einfach nur schrecklich unwissend). Dies sollte sofort offensichtlich sein, da er vorschlägt, wie viel Code zum Kopieren und Einfügen Sie schreiben. Die Bereinigung für jede dieser catch-Anweisungen ist genau gleich . Das ist ein Wartungs-Albtraum, von der Lesbarkeit ganz zu schweigen.
Kurz gesagt: Dies ist das Problem, für dessen Lösung RAII erstellt wurde (nicht, dass es andere Probleme nicht löst).
Was mich an dieser Vorstellung verwirrt, ist, dass es im Allgemeinen rückständig ist, wie die meisten Leute behaupten, dass RAII schlecht ist. Im Allgemeinen lautet das Argument "RAII ist schlecht, weil Sie Ausnahmen verwenden müssen, um Konstruktorfehler zu signalisieren. Sie können jedoch keine Ausnahmen auslösen, da es nicht sicher ist und Sie viele catch
Anweisungen benötigen, um alles zu bereinigen." Das ist ein kaputtes Argument, weil RAII das Problem löst , das der Mangel an RAII verursacht.
Höchstwahrscheinlich ist er gegen RAII, weil es Details verbirgt. Destruktor-Aufrufe sind bei automatischen Variablen nicht sofort sichtbar. Sie erhalten also Code, der implizit aufgerufen wird. Einige Programmierer hassen das wirklich. Anscheinend catch
ist es eine bessere Idee , drei Anweisungen zu haben, die alle dasselbe mit Code zum Kopieren und Einfügen tun.
...
", während sich meine Frage auf "Soll ich besser fangen...
oder<specific exception>
bevor ich erneut wirf" konzentriert