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 deprecatedthrow(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 machestring 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 zurechtIch 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