virtuelle vererbung bei std exception klassen
-
wenn ich das so sehe, stellt sich mir die frage: warum willst du deine basisklasse überhaupt von std::exception ableiten? lass das doch einfach. es bringt so, wie du es beschrieben hast, keine vorteile.
-
ghorst schrieb:
wenn ich das so sehe, stellt sich mir die frage: warum willst du deine basisklasse überhaupt von std::exception ableiten? lass das doch einfach. es bringt so, wie du es beschrieben hast, keine vorteile.
doch: ich muss nur std::exception fangen, falls alles andere schief gehen sollte. ansonsten müsste ich jeweils einen zweiten catch-block schreiben, der auch wieder nur eine methode namens what aufruft.
mfg foobar
-
du willst dann also immer die std::exception fangen und dann hochcasten, da du ja nur die kinder fangen kannst? welchen sinn siehst du in dem vorgehen?
ich halte es für sinnvoller nur das zu fangen, was du wirklich behandeln kannst. man weiß ja auch, was, wo und wann überhaupt geworfen werden kann. wenn du nicht weißt, was schiefgegange ist, kannst du es auch nicht sinnvoll behandeln. wenn du nur aufräumen willst, hilft dir der catch(...)-block. auf unterster ebene kannst du dann ja noch ein handler für die std::exception aufstellen, allerdings weiß ich nicht, was du damit fangen willst.
-
ghorst schrieb:
du willst dann also immer die std::exception fangen und dann hochcasten, da du ja nur die kinder fangen kannst? welchen sinn siehst du in dem vorgehen?
ich halte es für sinnvoller nur das zu fangen, was du wirklich behandeln kannst. man weiß ja auch, was, wo und wann überhaupt geworfen werden kann. wenn du nicht weißt, was schiefgegange ist, kannst du es auch nicht sinnvoll behandeln. wenn du nur aufräumen willst, hilft dir der catch(...)-block. auf unterster ebene kannst du dann ja noch ein handler für die std::exception aufstellen, allerdings weiß ich nicht, was du damit fangen willst.
Eieiei.
Du musst hier 2 Fälle unterscheiden:- Eine bestimmte Methode will bestimmte Fehler behandeln und weiss genau was für Exceptions da fliegen könnten. In dem Fall fängst du natürlich nur das was du behandeln kannst/willst.
- Eine Methode will irgendwas machen und bloss wissen ob's geklappt hat oder nicht. Falls nicht möchtest du ne schöne Fehlermeldung ausgeben bzw. wenigstens ins Logfile schreiben. In dem Fall fängst du erstmal eine "std::exception const&", und zusätzlich "...". Der Vorteil ist dass du wenn der erste Handler greift eine schöne Referenz auf eine Exception hast, die du für die Fehlerausgabe/Logmessage verwenden kannst. Du kannst z.B. über type_id() den dynamischen Typ feststellen, und du kannst über .what() eine minimale Fehlermeldung rausbekommen. Das ist oft sehr sehr nützlich.
Und solange sich alle beteiligten Libraries/Programmteile daran halten alle ihre Exceptions von std::exception abzuleiten funktioniert das auch schön.
Blöd wird es nur wenn eine Exception Klasse mehrere Kopien von std::exception erbt, dann kann man die nämlich nichtmehr als "std::exception const&" fangen, da hier eine doofe "ambiguity" existiert: auf welche Kopie von std::exception soll die Referenz dann zeigen? (bzw. wenn man Kopien fängt, was man eigentlich nie sollte: welche std::exception soll kopiert werden?)
Daher ist "virtual" gut wenn man Exception Hierarchien bastelt. Blöderweise macht einem die std. Library einen Strich durch die Rechnung, da die std. Exception Klassen NICHT virtual von std::exception abgeleitet sind.
-
also ich habe meistens verschachtelte try-blöcke, die ergeben sie sich irgendwie immer wie von selbst, wenn man ein etwas größeres projekt hat, daher ist witzlos in jeder etage den logfile voll zu spammen.
zu deinem 2) punkt: hübsche fehler, die man leider nicht behandeln kann und von denen man nicht weiß, ob sie nicht noch mehr müll hinterlassen haben. sollte man wirklich schlicht ignorieren, aber wenigstens einen hübschen logeintrag hinterlassen...
ich weiß nicht, von der art der fehlerbehandlung halte ich irgendwie sehr wenig. ich reiche fehler immer durch bis sich jemand findet, der damit was anfangen kann und wenn sich keiner findet, hat an immer noch terminate().
-
hustbaer schrieb:
Daher ist "virtual" gut wenn man Exception Hierarchien bastelt. Blöderweise macht einem die std. Library einen Strich durch die Rechnung, da die std. Exception Klassen NICHT virtual von std::exception abgeleitet sind.
O_o
ich habe gar nicht gemerkt, dass das nicht geht. in dem fall werde ich wohl in den sauren apfel beißen müssen und leite meine OOM-Klasse nicht von bad_alloc ab.danke für die hilfe!
mfg foobar
-
bad_alloc ist kein SystemError.
man kann nicht seine eigene hierachie in eine fremde hierachie mit vererbung einflechten.
-
Shade Of Mine schrieb:
bad_alloc ist kein SystemError.
man kann nicht seine eigene hierachie in eine fremde hierachie mit vererbung einflechten.
ich verstehe die aussage nicht bzw nicht welche konsequenzen das hat.
mfg foobar
-
er will dir damit sagen:
catch(SystemError)
fängt kein bad_alloc, gleiches gilt für jede anderen exception der std.
-
es gibt eine bestehende exception hierachie. da ist std::exception, std::bad_alloc, std::logic_error und wie sie alle heissen drin.
nun kommt eine komplett andere hierachie:
SystemError, InvalidArgumentError, oder was weiss ich.Nun will der OP diese beiden hierachien verschmelzen indem SystemError von std::exception und std::bad_alloc erben soll. InvalidArgument soll dann wohl von x, y und z erben. etc.
das klappt nicht. es sind 2 unterschiedliche exception hierachien. man kann sie nicht verschmelzen.
-
ghorst schrieb:
also ich habe meistens verschachtelte try-blöcke, die ergeben sie sich irgendwie immer wie von selbst
Hm. Klingt für mich nach extrem unsauberem Design. Exceptions verwendet man nicht damit man sie an 100 Stellen fängt und vielleicht andere weiter wirft oder was auch immer. Exceptions verwendet man damit man sie an 100 Stellen wirft, und an ganz wenigen fängt.
zu deinem 2) punkt: hübsche fehler, die man leider nicht behandeln kann und von denen man nicht weiß, ob sie nicht noch mehr müll hinterlassen haben. sollte man wirklich schlicht ignorieren, aber wenigstens einen hübschen logeintrag hinterlassen...
ich weiß nicht, von der art der fehlerbehandlung halte ich irgendwie sehr wenig. ich reiche fehler immer durch bis sich jemand findet, der damit was anfangen kann und wenn sich keiner findet, hat an immer noch terminate().Cleanup findet in Destruktoren statt. Das einzige was dann noch zu tun übrig bleibt, ist den Umstand anzuerkennen, das was auch immer gemacht werden sollte, nicht gemacht werden konnte.
terminate() ist auch mein Freund, aber sicher nicht nur weil ich wo eine Exception gefangen habe die ich nicht kenne, bzw. von der ich nicht weiss wo sie herkommt.
Wenn etwas terminate()-würdiges passiert, dann soll man gefälligst gleich terminate() aufrufen, und nicht erst eine exception werfen.
Manchmal heisst das auch einen catch(...) Block zu haben wo einfach "log(...); terminate();" drinsteht, bzw. einen "Guard" der eben terminate() aufruft wenn eine Exception fliegt und er noch nicht "entschärft" wurde.