Statische Exception-Methoden vererben



  • Hallo zusammen,

    ich hatte heute eine Idee, habe sie aber nicht ganz umgesetzt bekommen, ich hoffe ihr könnt mir da ein wenig weiterhelfen. Es geht um statische Methoden in Exception-Klassen die ich gerne weitervererben würde. Mal als Beispiel:

    // MainException:
    static void checkString_empty(string testString) throw(MainException) {
    	if (testString.size() == 0) {
    		throw MainExcetion(ERROR_EMPTY_STRING);
    	}
    }
    

    diese könnte ich ja dann einfach per

    MainException::checkString_empty(...);
    

    überall einsetzen, was ich für eine recht angenehme Fehlerabfrage halte

    Nun würde ich aber auch gerne Ableiten können. Eine abgeleitete Klasse XYZ_Exception sollte dann natürlich eine XYZ_Exception werfen.
    Ist sowas irgendwie zu bewerkstelligen, oder muss ich sie dann für jede abgeleitete Klasse einen override machen?

    Vielen Dank schonmal!
    Narase



  • was willst du damit erreichen? wozu hat deine exception klasse diese statische methode? eine exception ist eine ausnahme, und nicht - so wie du es verwendest - eine klasse, die funktionen zur verfügung stellt, um gewisse invarianten zu überprüfen.



  • Die Idee dahinter ist halt dass ich einfach die Exceptionklasse auch direkt die Bedingung prüfen lasse, praktisch eine Abwandlung von assert(). Finde es angenehmer als in jede Klasse die ich schreibe die gleiche Methode zu implementieren die mir einen String prüft



  • Narase schrieb:

    in jede Klasse die ich schreibe die gleiche Methode zu implementieren die mir einen String prüft

    Warum packst du sie in eine Klasse?



  • Narase schrieb:

    Die Idee dahinter ist halt dass ich einfach die Exceptionklasse auch direkt die Bedingung prüfen lasse, praktisch eine Abwandlung von assert(). Finde es angenehmer als in jede Klasse die ich schreibe die gleiche Methode zu implementieren die mir einen String prüft

    wenn du gewisse vor- (oder nachbedingungen, in diesem sinne: https://de.wikipedia.org/wiki/Design_by_contract ) prüfen willst, ist es momentan wohl am besten, das makro "Ensures" aus der guideline support library zu verwenden. der vorteil davon ist, dass es in zukunft sehr leicht möglich sein wird, dass dann direkt in C++ (in form von attributen) ausdrücken zu können.

    du willst nämlich sicher nicht, dass am ende ein user mit irgendeiner seltsamen fehlermeldung wie "string länge ist null" konfrontiert wird, oder? überlege dir gut das design!

    #include "gsl_assert.h"
    //...
    void (string foo) {
      Expects(foo.size() > 0);
      //...
    }
    
    //später
    void (string foo) 
      [[expects: foo.size() > 0]]
    {
     //...
    }
    

    (hier: https://github.com/Microsoft/GSL/ )

    auf deine art und weise muss du überall, wo du deine invarianten überprüfen willst, die exception-klasse einbinden. die exception-klasse brauchst du aber eigentlich nur, wenn du sie wirfst - oder an der stelle, wo du den fehler behandelst.

    übrigens:
    explizite exception-spezifikationen sind deprecated

    throw(MainException) //geht bald (!) nicht mehr!
    


  • manni66 schrieb:

    Narase schrieb:

    in jede Klasse die ich schreibe die gleiche Methode zu implementieren die mir einen String prüft

    Warum packst du sie in eine Klasse?

    Wo soll ich sie sonst haben? Statisch in irgendeiner Source? Eine Klasse die die Funktion braucht muss sie auch implementieren.

    @dovve
    das hört sich soweit gut an, gilt es dann nur für Vorbedingungen?
    Wenn ich zb sowas mache

    string s;
    s = readLineFromAFile().trim();
    

    würde die neue Funktion so etwas abfangen können oder steh ich damit dann eher schlecht dar?



  • Narase schrieb:

    Statisch in irgendeiner Source?

    Nein

    Narase schrieb:

    Eine Klasse die die Funktion braucht muss sie auch implementieren.

    Nein.



  • Narase schrieb:

    Wo soll ich sie sonst haben? Statisch in irgendeiner Source? Eine Klasse die die Funktion braucht muss sie auch implementieren.

    Wie wäre es als freie Funktion in einem Namespace? Wobei ich noch immer nicht so wirklich den Sinn sehe.

    Narase schrieb:

    das hört sich soweit gut an, gilt es dann nur für Vorbedingungen?

    Expects für Pre- und Ensures für Post-Conditions. Siehe: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Ri-pre

    Narase schrieb:

    Wenn ich zb sowas mache

    string s;
    s = readLineFromAFile().trim();
    

    würde die neue Funktion so etwas abfangen können oder steh ich damit dann eher schlecht dar?

    std::string hat kein trim() - kommst du von Java? Das würde auch erklären, warum du ne statische Funktion in der Klasse willst und wo das throw(MainException) herkommt.

    Aber allgemein: WAS soll da abgefangen werden (was ist "so etwas")?
    a) Fehler beim Lesen -> könnte ne Exception sein
    b) String ist nach dem trim leer -> sowas sollte keine Exception sein, das ist ja ein ganz normaler Fall und keine Ausnahme, oder nicht?



  • Das mit dem Java war fast richtig. War meine erste Sprache, hab aber in letzter Zeit viel mit Qt gearbeitet, da gibt es trimmed(), komme wohl langsam etwas durcheinander.

    Mein Grundgedanke ist konkret dieser: Ich lese daten aus einer XML aus. Nun sollen die Daten in der XML nicht leer sein, ich könnte also hingehen und jedes mal

    if (string.size() < 1){
        throw Exception("Blah");
    }
    

    dazwischen packen. Das würde aber meinen Code zumüllen. Ich könnte auch jedes mal sowas implementieren

    string Classname::checkString(string test, string msg){
        if (test.size() < 1){
            throw Exception(msg);
        }
        return test;
    }
    

    Diese Methode könnte ich einfach um den read herumpacken, damit wäre ich den Klotz schonmal weg.
    Aber wenn ich sie nun in verschiedenen Klasse brauche könnte ich sie...
    1. ... in jeder Klasse definieren. Abgelehnt wegen Redundanz
    2. ... als public in einer Klasse definieren und eine Instanz von ihr erstellen. Auch abgelehnt
    3. ... in eine Source packen und sie einfach so statisch machen. Fände ich auch unschön, außerdem kommt Eclipse mit sowas nicht sonderlich gut zurecht

    Ich habe 2 Klassen, beide haben ihre eigene Execption-Klasse.
    class Person; PersonException
    class Animal; AnimalException
    Beide Klasse lesen im Konstruktor ihre Attribute aus einer XML (warum, lassen wir mal dahingestellt).
    Wenn beide Exceptions von MainException erben und es so funktionieren würde wie ich mir das vorstelle, könnte ich einfach beide male die jeweilige Exception-Klasse nutzen um die Prüfungen der XML-Daten zu machen. Da es nicht funktioniert bin ich auf andere Methoden angewiesen, von denen jede so ihre Nachteile hat, ganz oben dabei die Redundanz



  • 4. ... Eine Funktion schreiben. Ohne static!

    Dein Konzept mit Zuordnung Klasse <-> Exceptionklasse ist sehr merkwürdig. Aber wenn du es unbedingt so willst:

    5. ... eine Templatefunktion mit der Exeptionklasse als Templateparameter. Ohne static! Mit using kann man die Schreibweise sogar abkürzen.



  • Die Idee mit dem Template ist gar nicht mal so verkehrt
    Wie genau würde das mit der Kürzung per using funktionieren? Hab mir gerade die cpp-Referenz dazu durchgelesen, so ganz komme ich nicht dahinter.



  • Narase schrieb:

    Wie genau würde das mit der Kürzung per using funktionieren? Hab mir gerade die cpp-Referenz dazu durchgelesen, so ganz komme ich nicht dahinter.

    Hm, war leider ein Irrtum, das geht nur mit Typen, nicht mit Funktionen.

    Aber wie gesagt, dein Konzept ist merkwürdig. Der Typ der Exception sollte Informationen über den Fehler beinhalten und nicht über die Klasse, aus der sie geworfen wurde.



  • Wahrscheinlich hast du recht, ich werd mal schauen dass ich mir ein kleines Konzept mit Nicht-Klassen Methoden erdenke.
    Vielen Dank dir


Log in to reply