Ich habe gerade einen sehr subtilen Fehler in unserem Code behoben, der durch das Slice einer Ausnahme verursacht wurde, und jetzt möchte ich sicherstellen, dass ich genau verstehe, was passiert ist.
Hier ist unsere Basisklassen-Ausnahme, eine abgeleitete Klasse und relevante Funktionen:
class Exception
{
public:
// Konstruktion
Exception(int code, const char* format="", ...);
virtual ~Exception(void);
protected:
private:
int mCode; // werfende Stelle setzt das
char mMessage[Exception::MessageLen]; // werfende Stelle sagt das FIXME: Verwende String
};
class Derived : public Exception {
public:
Derived (const char* werfendeStelleSagte) : Exception(1, werfendeStelleSagte) {};
};
void innercall {
throw Derived("Schlimme Dinge sind passiert!");
}
void outercall {
try {
innercall();
}
catch(Exception& e)
{
printf("Ausnahme hier gesehen! %s %d\n", __FILE__, __LINE__);
throw e;
}
}
Der Fehler bestand natürlich darin, dass outercall am Ende eine Ausnahme wirft, anstatt eine abgeleitete Ausnahme. Mein Fehler resultierte daraus, dass weiter oben im Aufrufstapel der Versuch, die abgeleitete Ausnahme zu fangen, fehlschlug.
Jetzt möchte ich nur sicherstellen, dass ich verstanden habe - Ich glaube, dass an der Stelle 'throw e' ein neues Exception-Objekt erstellt wird, das einen Standard-Kopierkonstruktor verwendet. Ist das wirklich, was passiert?
Wenn ja, darf ich die Kopierkonstruktoren für Objekte, die geworfen werden sollen, sperren? Ich würde wirklich bevorzugen, dass dies nicht noch einmal passiert, und unser Code hat keinen Grund, Exception-Objekte zu kopieren (soweit ich weiß).
Bitte keine Kommentare dazu, dass wir unsere eigene Ausnahmehierarchie haben. Das ist etwas alter Design, an dem ich arbeite, um es zu korrigieren (Ich mache gute Fortschritte. Ich habe die selbstgemachte String-Klasse beseitigt und viele der selbstgemachten Container).
UPDATE: Um es klarzustellen, ich hatte den Fehler behoben (indem ich 'throw e' in 'throw' änderte), bevor ich überhaupt die Frage gestellt habe. Ich wollte nur eine Bestätigung dessen, was passiert ist.
4 Stimmen
Ich weiß, du hast gesagt, dass du dir keine Sorgen um den anderen Kram machen sollst, aber nur zwei weitere Dinge: Lass deine
Exception
-Klasse vonstd::exception
erben und fange Dinge mitconst &
ab.0 Stimmen
Was ist der Vorteil von const beim Fangen? Ich fange immer per Referenz, aber warum const? (nicht dass ich das im Moment sowieso mit dieser Klasse machen kann, aber eines Tages...)
3 Stimmen
@Kohne: Der Vorteil von const in diesem Fall ist ähnlich wie in jedem anderen Fall - Sie geben deutlich an, dass Sie nicht beabsichtigen, den Zustand des Objekts zu ändern, und dass der Compiler sicherstellen sollte, dass Sie dies nicht tun - die Idee hinter const ist, dass unveränderliche Objekte einfacher zu handhaben sind (d.h. Debuggen, Testen, den Code als korrekt nachweisen), da sie beim Schreiben von referenziell transparentem Code helfen.
0 Stimmen
OK, also einfach die normalen Vorteile. Ich wollte sicherstellen, dass es nichts Subtiles und Spezifisches für Ausnahmen gibt, das ich nicht kenne. Danke!