Ich habe gerade einen sehr subtilen Fehler in unserem Code behoben, der durch das Schneiden einer Ausnahme verursacht wurde, und ich möchte jetzt sicherstellen, dass ich genau verstehe, was passiert ist.Exception Slicing - liegt das an generiertem Copy-Konstruktor?
Hier ist unsere Basis Ausnahmeklasse, eine abgeleitete Klasse, und relevante Funktionen:
class Exception
{
public:
// construction
Exception(int code, const char* format="", ...);
virtual ~Exception(void);
<snip - get/set routines and print function>
protected:
private:
int mCode; // thrower sets this
char mMessage[Exception::MessageLen]; // thrower says this FIXME: use String
};
class Derived : public Exception {
public:
Derived (const char* throwerSays) : Exception(1, throwerSays) {};
};
void innercall {
<do stuff>
throw Derived("Bad things happened!");
}
void outercall {
try {
innercall();
}
catch(Exception& e)
{
printf("Exception seen here! %s %d\n", __FILE__, __LINE__);
throw e;
}
}
Der Fehler war natürlich, dass outercall endet eine Ausnahme zu werfen, statt eines abgeleitet. Mein Fehler resultierte aus höheren Call-Stack-Versuchen, den Abgeleiteten Fehler zu fangen.
Jetzt möchte ich nur sicherstellen, dass ich verstehe - ich glaube, dass in der "throw e" -Zeile ein neues Exception-Objekt erstellt wird, mit einem Standard-Copy-Konstruktor. Geht das wirklich so?
Wenn ja, darf ich Kopierkonstruktoren für Objekte ausschließen, die geworfen werden? Ich würde wirklich bevorzugen, dass dies nicht wieder passiert, und unser Code hat keinen Grund, Exception-Objekte (die ich kenne) zu kopieren.
Bitte keine Kommentare zu der Tatsache, dass wir unsere eigene Ausnahme-Hierarchie haben. Das ist ein bisschen altes Design, an dem ich arbeite, um es zu korrigieren (ich mache gute Fortschritte. Ich habe die Klasse der selbstgewachsenen Strings und viele der selbst gezogenen Container los.)
UPDATE: Um es klar zu sagen, ich hatte den Fehler behoben (indem ich 'Wurf e' in 'Wurf' änderte), bevor ich die Frage überhaupt stellte. Ich wollte nur bestätigen, was vor sich geht.
Ich weiß, dass du gesagt hast, dass du dir über die anderen Sachen keine Sorgen machen musst, sondern nur zwei andere Dinge: mach deine 'Exception' Klasse von' std :: exception' und erhalte Dinge durch 'const &'. – GManNickG
Was hat den Vorteil, als const zu fangen? Ich fange immer durch Verweis, aber warum const? (Nicht, dass ich das im Moment mit dieser Klasse machen könnte, aber eines Tages ...) –
@Kohne: Der Vorteil von const in dieser Einstellung ist ähnlich wie in jeder anderen Einstellung - du spezifizierst klar die Absicht, die du nicht hast t beabsichtigen, den Zustand des Objekts zu ändern, und dass der Compiler sicherstellen sollte, dass die unveränderlichen Objekte einfacher zu verstehen sind (dh debuggen, testen, Code korrekt prüfen), da sie beim Schreiben referentiell helfen transparenter Code –