Welchen Rückgabewert?



  • wenn es nur 2 möglichkeiten gibt (geklappt oder nicht), dann nimm 'bool'.
    gibt es einige mehr (statusmeldungen etc.), dann bastel' dir ein 'enum' dafür.
    🙂
    edit: exceptions würde ich auch eher nicht nehmen...



  • Ich glaub nicht, dass Exceptions so teuer sind. Beim C++-Linux-Kernel-Projekt haben die glaube ich von 2,3 µs für eine geworfene Exception gemessen und im Fehlerfall sind die Laufzeiten ja eh nicht mehr so schlimm...

    Ganz zu schweigen davon, dass der meiste Code ja eh nicht kritisch ist im Bezug auf die Geschwindigkeit. Und eine Exception erzwingt eine Behandlung, ein Rückgabewert nicht. So kann man eher Fehler in sein Programm einschleusen!



  • rüdiger schrieb:

    Ich glaub nicht, dass Exceptions so teuer sind. Beim C++-Linux-Kernel-Projekt haben die glaube ich von 2,3 µs für eine geworfene Exception gemessen und im Fehlerfall sind die Laufzeiten ja eh nicht mehr so schlimm...

    hat der linux-kernel kein exception handling eingebaut?
    sowas wie

    __try
    {
      // irgendeine aktion
      // die schief gehen kann
      // auch x/0 oder sowas
    }
    __except (filterausdruck)
    {
      // ist schief gegangen
    }
    

    ich kenne ein OS, das hat sowas 😉



  • rüdiger schrieb:

    Ich glaub nicht, dass Exceptions so teuer sind. Beim C++-Linux-Kernel-Projekt haben die glaube ich von 2,3 µs für eine geworfene Exception gemessen und im Fehlerfall sind die Laufzeiten ja eh nicht mehr so schlimm...

    Ganz zu schweigen davon, dass der meiste Code ja eh nicht kritisch ist im Bezug auf die Geschwindigkeit. Und eine Exception erzwingt eine Behandlung, ein Rückgabewert nicht. So kann man eher Fehler in sein Programm einschleusen!

    Kostet das try gar nichts? Was Werfen + Fangen kostet ist ja dann eigentlich egal. Während in Java nahezu jeder Fehlerfall als Exception gewertet wird, bin ich mir in C++ da nie sicher. Eine Exception in C++ werfe ich eigentlich nur wenn gröberes passiert. Ein "void RemoveFile() throws FileNotFoundException" habe ich in C++ eigentlich noch nie gesehen (abgesehen vom throws jetzt :p). Deswegen habe ich bisher eigentlich in C++ immer nur wirklich kritische Ausnahmefälle ala StdLib BadAlloc als Exception angesehen. Soll ich das ändern?

    MfG SideWinder



  • rüdiger schrieb:

    Ich glaub nicht, dass Exceptions so teuer sind. Beim C++-Linux-Kernel-Projekt haben die glaube ich von 2,3 µs für eine geworfene Exception gemessen und im Fehlerfall sind die Laufzeiten ja eh nicht mehr so schlimm...

    Ganz zu schweigen davon, dass der meiste Code ja eh nicht kritisch ist im Bezug auf die Geschwindigkeit. Und eine Exception erzwingt eine Behandlung, ein Rückgabewert nicht. So kann man eher Fehler in sein Programm einschleusen!

    Kostet das try gar nichts? Was Werfen + Fangen kostet ist ja dann eigentlich egal. Während in Java nahezu jeder Fehlerfall als Exception gewertet wird, bin ich mir in C++ da nie sicher. Eine Exception in C++ werfe ich eigentlich nur wenn gröberes passiert. Ein "void RemoveFile() throws FileNotFoundException" habe ich in C++ eigentlich noch nie gesehen (abgesehen vom throws jetzt :p). Deswegen habe ich bisher eigentlich in C++ immer nur wirklich kritische Ausnahmefälle ala StdLib BadAlloc als Exception angesehen. Soll ich das ändern?

    MfG SideWinder



  • Exceptions sind Ausnahmesituationen, die im Normalfall nicht auftreten, sich aber im Ernstfall nicht verhindern lassen. Wenn beispielsweise eine vom Nutzer angegebene Datei nicht gefunden wurde ist das keine Ausnahme, sondern zu erwarten (immer vom DAU ausgehen). Ist es dagegen eine Systemdatei oder eine, die zur ordnungsgemäßen Installation des Programms normalerweise gehört, ist das schon eher eine Ausnahme, da man im Normalfall davon ausgehen kann, dass das Öffnen der Datei klappt.
    Mit kritisch oder nicht hat das IMO nichts zu tun.

    Wobei Exceptions in C++ eigentlich nicht eingeführt wurden, um Fehlerbehandlung zu erzwingen, sondern um Fehler über mehrere Schichten hinweg werfen zu können, ohne dass sie zwischendurch explizit propagiert werden müssen...



  • @SideWinder
    Ich weiß nicht genau was das try-kostet in einem nicht-Fehlerfall. Das hängt zu stark von der Implementierung ab. Ein Compiler muss den Stack-Aufroll-Code wohl erst einbauen, wenn ein try/catch-Handler benutzt wird. Das kann natürlich zu einem kleinen Overhead führen.

    Das muss man wohl für jede Implementierung testen.

    Wobei wie Side schon gesagt hat ein void RemoveFile() throws FileNotFoundException wohl auch deshalb nicht sinnvoll ist, weil es keine wirkliche Ausnahme bildet und die Situation schlecht behandelbar wird. (Wenn C++ Conditions hätte, wäre das was anderes *säufz*)



  • Jap, das bestätigt mir, dass C++-Exceptions ganz andere Aufgaben haben als C#/Java-Exceptions. Werde ich bei meinem Stil bleiben: try-catch im main() und brav "Linux hat einen Ausnahmefehler verursacht" als Fehlermeldung in die MessageBox einfügen 😉

    MfG SideWinder



  • SideWinder schrieb:

    Jap, das bestätigt mir, dass C++-Exceptions ganz andere Aufgaben haben als C#/Java-Exceptions.

    Wie genau sind die Exceptions in C#/Java anders?

    Bei meiner (eher knappen) Java-Erfahrung hatte ich das Gefühl, dass das im Prinzip nicht so unterschiedlich sei.



  • In Java ist es zB durchaus üblich auch Exceptions in solchen DAU-Fällen (bzw. normalen Ausnahmefällen) zu werfen. Rhetorisches Beispiel wie das in C++ aussehen würde:

    void sort (T* arr, size_t len) throws IndexOutOfBoundsException // sowas
    {
        if(!arr) throw InvalidPointerException(); // sowas
        // do sort
    }
    
    // ich würde das eher so implementieren:
    void sort (T* arr, size_t len)
    {
        // do sort
    }
    
    // bzw. wenn schon ein safe dann:
    void sort_s (T* arr, size_T len)
    {
        if(!arr) return;
    }
    

    MfG SideWinder



  • In Java werden Exceptions sogar dazu benutzt, um Alogrithmen zu implementieren.
    Jüngstes Beispiel das ich gesehen habe, war die Umsetzung des Composite-Musters. Dor wurde eine Basisklasse für Blätter und für Scharen genommen und jeweils in den nicht benötigten Methoden eine UnsupportedOperation-Exception geworfen. Sowas wäre für mich in C++ undenkbar, mal abgesehen davon, dass es nicht funktioniert, weil ds Programm daraufhin beendet werden würde.



  • @SideWinder
    Wo ist aber nun der genaue Unterschied? In C++ spricht ja nichts gegen die Verwendung von Exceptions in deinem Beispiel.

    @viande
    Wird ein Java-Programm nach dem Werfen einer ungefangenen Exception nicht beendet?



  • darthdespotism schrieb:

    In C++ sind Exceptions normalerweise eine schlechte Entscheidung.

    Der Erfinder von C++ ist da aber ausdrücklich anderer Meinung als Du!

    viande schrieb:

    Sowas wäre für mich in C++ undenkbar

    Auch hier ist Stroustrup anderer Meinung. Zumindest weist er in "The C++ Programming Language" explizit auf diese Möglichkeit der Verwendung von Ausnahmen hin. Ich hatte zwar beim Lesen den starken Eindruck, dass Stroustrup selbst nie solchen Code schreiben würde aber auch, dass er solchen Code durchaus für legitim hält.

    So. Ich will jetzt nicht durch Autoritäts-Zitate argumentieren aber ich denke doch, dass man vorsichtig sein sollte, bevor man pauschal "ist schlecht" ruft, vor allem, wenn Leute, die sich viele Gedanken darum gemacht haben, andere Meinungen vertreten.



  • rüdiger schrieb:

    @SideWinder
    Wo ist aber nun der genaue Unterschied? In C++ spricht ja nichts gegen die Verwendung von Exceptions in deinem Beispiel.

    Ich weiß nicht, ob SideWinder das meinte, aber in diesem Beispiel würde ich persönlich in C++ nicht mit Ausnahmen arbeiten sondern den Code ungetestet durchrasseln lassen -- also undefiniertes Verhalten produzieren. Höchstens im Debug-Code mit Assertions die Gültigkeit der Parameter überprüfen.

    Allgemein ist IMHO eine der Stärken von C++, dass die Standard-Algorithmen eben gerade *keine* Gültigkeitstests ausführen. Für den Raketenbau mag das ungeeignet sein, für viele andere Programme aber ist es ideal. Gültigkeitstets kann man dann auf eine höhere Ebene packen und sich drauf verlassen, dass keinerlei redundante Tests geschehen.



  • Hi,

    ich habe hier wohl eine etwas andere Position ... ich verwende jedenfalls "reichlich" exceptions in C++. Für mich gehören sie zur Schnittstelle einfach dazu .. in der jeweiligen Klasse sieht der Anwender anhand der deklarierten exceptions auf einen Blick, was ihn an Ausnahmesituationen erwartet. Das geht mit Returncodes nicht besser - ganz zu schweigen vom "Kontrollflußärger", den der Anwender mit Returncodes hat....
    Ich hätte im "remove_file()-Beispiel" durchaus eine FileNotFoundException geworfen (wüsste auch nicht, was dagegen spräche) und zusätzlich eine "bool file_exists();" spendiert.
    Wer einfach nur ein File entfernen möchte, für den ist die Nichtexistenz des Files ebenso eine unerwartete Situation, wie ein Plattenlesefehler - er wird nicht böse über eine exception sein.
    Wer nicht genau weiß, ob es das File gibt und (direkt in der Nähe des remove-Aufrufs) noch einen Backupplan in der Hand hat, kann vorher file_exists() aufrufe (oder die entsprechende FileNotFound-Exception fangen).
    Zum Thema "Performance-im Gutfall" mache ich mir nicht allzuviele Sorgen: Wenn man Ähnliches anhand von Returncodes feststellen will, "kostet" das ebenfalls (vom Verwaltungsstress" ganz zu schweigen).

    Übrigens bin ich auf dieses Vorgehen ganz ohne Java gekommen (wenn es mich auch freut, dass man es sich in Java noch konsequenter angewöhnt hat)... 😉

    Gruß,

    Simon2.



  • rüdiger schrieb:

    @viande
    Wird ein Java-Programm nach dem Werfen einer ungefangenen Exception nicht beendet?

    Nach einer ungefangen glaube ich schon. Sonst nicht.



  • viande schrieb:

    rüdiger schrieb:

    @viande
    Wird ein Java-Programm nach dem Werfen einer ungefangenen Exception nicht beendet?

    Nach einer ungefangen glaube ich schon. Sonst nicht.

    Ist doch bei C++ nicht anders.



  • Vielen Dank für die Antworten. Ich hatte die letzten Tage frei...

    Ich werde für den Programmfluß dann Rückgabewerte verwenden und für das Interface zu anderen Programmteilen Exceptions.


Anmelden zum Antworten