Elegante weitergabe von Exceptions

Gast #6019547
Moin,

ich wechsel gerade (zumindest teilweise) von der Embedded 
C-Programmierung zu C++. Diese Frage gehört bestimmt zum 
Grundrepertoire.

In C habe ich bisher z.B. eine Funktion gehabt:
1
int irgendwas(){
2
}

Diese hat neben dem Ergebnis auch Fehlercodes übertragen (z.B. -1, -2, 
etc..). Wenn ich nun eine Funktion habe, die nur true/fase zurückliefern 
soll, jedoch auch Fehler weil z.B. eine Datei nicht geöffnet werden 
könnte, möchte ich das nun sinnigerweise übr try/catch lösen.

Wie formatiere ich nun elegant und praxisorientiert diese Fehler? Soll 
ich in der Funktion lauter "throws" einsetzen? Sollen diese Fehlercodes 
oder Strings zurückliefern? Und wenn ich die Funktion "irgendwas" 
aufrufe innerhalb eines try/catch blocks, gebe was mache ich mit dem 
Fehler?

Ok, was ich damit anstelle ist meine Sache (speichern, ausgeben, 
verwerfen, etc.) aber ich  frage mich, ob meine Herangehensweise richtig 
ist oder ich das Konzept nicht ganz richtig verstanden habe. Sollte ich 
z.B. Fehlercodes zurückgeben, muss ich diese wieder irgendwo definieren, 
was ich mir ziemlich umständlich vorstelle.

Danke!
Gast #6019581
throw ist nicht schlecht
aber manchmal gibt es auch lässliche Fehler
und du möchtest die laufende Routine deswegen noch nicht sofort 
unterbrechen;
dann könntest Du eine eignene Fehlerbehandlung implementieren
wie:
void dontThrowThisErrorJustYet(int fehlercode, std::string 
fehlermeldung)

das schreibt dann zB ein Logfile oder speichert die Warnungen (sind ja 
mehr oder weniger solche) für einen späteren Gebrauch.

Gespeichertes wieder hervorzaubern zu einem günstigen Zeitpunkt kannst 
Du ja immernoch

Und die Frage ob Du code oder Meldung willst beantwortet sich relativ 
einfach
User haben sich daran gewöhnt beides zu sehen,
Informativer ist aber meist eine ausssagekräftige FehlerMELDUNG.

Ein FehlerCODE ist nützlicher für den Programmierer,
manches lässt sich innerhalb des Codes reparieren und braucht 
nichteinmal Nutzerintervention,
das kann dann über eine int leichter identifiziert werden als über einen 
string intern.

Ausserdem hilft code bei der Auffindung innerhalb des Quelltextes
(001265 .. datei 0012 Routine 6 Fehleroption 5 zB)
oder man macht sich selbst Regeln
(001265 00 user input, 12 formatting error, 6 numerical, 5 dateformat)

Was das gliedern in Tabellen und die damit verbundenen übersetzung in 
FehlerMELDUNGEN erleichtert.

Was die lieber ist und womit Du Dich wohler fühlst ist Dir überlassen.
(ich benutz mal so mal so um ehrlich zu sein)
#6019603
Eine der wichtigsten Grundregeln ist sich für eine der beiden Varianten 
zu entscheiden. Entweder man bleibt (z.B. wegen Performance) bei 
klassischen Fehlercodes bzw. Varianten davon (siehe std::expected) oder 
man setzt auf Exceptions.

Da Exceptions in den meisten Fällen Domain-spezifisch sind bleibt es dir 
überlassen wie du die gestaltest. Die meisten Exceptions in der 
Standardbibliothek enthalten Strings, manche Enums und manche überhaupt 
komplett andere Typen die in dem Context allerdings Sinn machen (C++20 
nonexistent_local_time etwa).

Folgender CppCon Talk fasst ganz gut zusammen worauf man achten sollte:
https://www.youtube.com/watch?v=W6jZKibuJpU
Gast #6019723
Es gibt nur eine Grund für Exceptions, Konstruktoren bei denen ein 
Fehler auftreten kann. Alles andere kann man herkömmlich abfangen und 
sollte es auch.
Gast #6025480
So wie es aussieht geht hier die Meinung ja eher zum klassischen 
Fehlercode.
Packe ich dann mein ENUM mit den sprechenden Codes in z.B. meine Klasse 
unter public?

Vermutlich wrde ich es so lösen, dass gravierende Probleme als throw 
zurückgeworden werden und inhaltliche Probleme mit einem enum behandelt 
werden als normaler Rückgabewert. Ist das ein eleganter Lösungsweg?
#6025486
Jens schrieb:
> So wie es aussieht geht hier die Meinung ja eher zum klassischen
> Fehlercode.

Ich denke eher: it depends.

Mache Dir klar, was Du unter "Fehler" verstehst. Z.B. ist die leere 
Menge beim Suchen kein Fehler im engeren Sinn, sondern ein ganz normales 
Ergebnis. In dieser Art gibt es viele Operationen. Manchmal hat man die 
Möglichkeit, für diesen Fall sog. invalide Objekte zurückzugeben. Oder 
man nimmt std::optional<> und externalisiert den ungültigen Zustand des 
Objektes.

Nur bei echten, tragischen Fehlern, die auch wahrscheinlich mit geringer 
Häufigkeit vorkommen, werden dann Ausnahmen verwendet.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.