Schnitstellen in C++?
-
theta schrieb:
Eine kleine Korrektur: der Destruktor sollte virtual sein:
class MyInterface { public: virtual void doThat() = 0; protected: virtual ~MyInterface() { } };
-
Ups, das Zitat ist etwas verunglückt
-
Gilli82 schrieb:
ich komme aus der Javawelt und muss leider ein paar Klassen nach C++ portieren.
Oha!
Beachte, dass Du ein Java-Design nicht 1:1 nach C++ übertragen kannst. Das Ergebnis ist meist genauso schlecht wie eine Wort-für-Wort-Übersetzung einer Videorekorder-Anleitung von Chinesisch auf Englisch. (Kein Scherz!)Gilli82 schrieb:
Gibt es hier was Vergleichbares wie Interfaces?
Es gibt abstrakte Klassen.
class abc { public: virtual ~abc() {} // <-- brauchst Du, um Objekte "polymorph löschen" zu klönnen virtual void foo(int) = 0; // <-- abstrakt virtual int bar() const = 0; // <-- auch abstrakt };Gilli82 schrieb:
Wie gut sind Exceptions in C++ umgesetzt?
Du wirst erst mal das Stack-Trace-Feature vermissen. Wenn eine Ausnahme fliegt, die nicht gefangen wird, bricht das Programm sofort ab ohne einen Mucks -- es sei denn, Du hast einen entsprechenden Handler installiert. Desweiteren funktionieren "exception specifications" anders in C++. In Java werden die statisch überprüft, in C++ nicht -- daher sind sie eher nutzlos! Die beste Praxis ist es, keine Funktionen mit exception specifications zu dekorieren. Also:
void dingsbums() throw(std::runtime_error);ist nix gut, wobei
/** * @throw std::runtime_error in case file xyz didn't exist. */ void dingsbums();okay ist. Mach Dich mit der Dokumentation Deines Compilers und Deines Debuggers vertraut. Unter'm Debugger lässt sich vieles leichter nachvollziehen und den Aufruf-Stack gibt's da auch zu sehen. Dein(e) Compiler/Standardbibliothek bietet eventuell einen schönen "STL-Debug-Modus" an, welcher allerlei Zusatzüberprüfungen zwecks Fehlerfrüherkennung macht. Das kann sehr praktisch sein.
Mit hoher Wahrscheinlichkeit wird das, was Du in C++ schreibst erstmal totaler Müll sein. Das war bei mir auch so.
Lerne die Sprache richtig. Nachdem Du die Sprache kennengelernt hast, lese das Buch "Effective C++" von Scott Meyers -- wenn möglich in der 3. Auflage.Nachtrag:
Als Java-Programmierer wirst Du vielleicht erst mal dazu neigen, alles in Klassen mit vielen virtuellen Elementfunktionen zu verpacken. Das ist nicht immer sinnvoll. C++ bietet auch andere Abstraktionsmöglichkeiten.Nachtrag2:
Mir fällt noch das Konzept der getrennten Übersetzung ein. Das hatte ich auch anfangs nicht sofort verstanden. Lass Dir das und die "one definition rule" von den schlauen Büchern erklären.Viel Spaß beim Lernen!
kk
-
@manni66:
Eine kleine Korrektur: der Destruktor sollte virtual sein:
Nö..

Entweder public virtual ODER protected non- virtual...
public virtual ist nur dann nötig wenn das Objekt, polymorph gelöscht werden soll (wie krümelkacker korrekt anmerkte).
Edit:
Das gilt für Klassen die als Interface / Basis Klasse dienen. Nur um den Kontext klarzustellen.
-
theta schrieb:
@manni66:
Eine kleine Korrektur: der Destruktor sollte virtual sein:
Nö..

Entweder public virtual ODER protected non- virtual...
public virtual ist nur dann nötig wenn das Objekt, polymorph gelöscht werden soll (wie krümelkacker korrekt anmerkte).
Edit:
Das gilt für Klassen die als Interface / Basis Klasse dienen. Nur um den Kontext klarzustellen.Aus Kompatibilitätsgründen zu anderen Compilern, der Lesbarkeit und der Reduktion von Fehlerquellen sollte man sich das aber angewöhnen.
Oder sehe ich das falsch?
-
Aus Kompatibilitätsgründen zu anderen Compilern, der Lesbarkeit und der Reduktion von Fehlerquellen sollte man sich das aber angewöhnen.
Das musst Du mir jetzt aber genau erklären...

Simon
-
Dankeschön für die vielen Antworten, besonders Krümelkacker. Das scheint ja doch alles ein wenig komplexer zu sein als ich dachte und ich habe nicht die Zeit um mich ewig in eine neue Sprache einzuarbeiten, darum werde ich dann doch warten bis der C++ Kollege wieder da ist, der macht das seit 10 Jahren. Ich denke mal gutes C++ kann man nicht so schnell lernen wie Java.
Danke trotzdem für die Hilfe.
Gruß Gilli
-
krümelkacker schrieb:
Desweiteren funktionieren "exception specifications" anders in C++. In Java werden die statisch überprüft, in C++ nicht -- daher sind sie eher nutzlos! Die beste Praxis ist es, keine Funktionen mit exception specifications zu dekorieren.
Eine Frage: Warum?
Ich arbeite hauptsächlich mit gcc, und dort ist es so, dass eine Exception nur "weitergeworfen" wird, wenn sie auch in der Spezifikation der Methode drinsteht (oder die Methode keine Spezifikation hat), ansonsten wird "terminate()" aufgerufen, und die Meldung ausgegeben welche Exception (mit what()-Ausgabe) zu dem Abbruch führt. Dank diesem Verhalten habe ich schon öfters fehlende "catch"-Blöcke finden können.
Also zurück zur Frage: Warum ist das nutzlos?
-
Herb Sutter im C++ Users Journal zu Exception Specifications:
http://www.gotw.ca/publications/mill22.htmHerb Sutters GOTW Reihe:
http://www.gotw.ca/gotw/082.htmSimon
Edit:
Und wenn ich schon dabei bin noch bezüglich public virtual / protected non-virtual Destruktor: http://www.gotw.ca/publications/mill18.htm
-
Yamakuzure schrieb:
Ich arbeite hauptsächlich mit gcc, und dort ist es so, dass eine Exception nur "weitergeworfen" wird, wenn sie auch in der Spezifikation der Methode drinsteht (oder die Methode keine Spezifikation hat), ansonsten wird "terminate()" aufgerufen, und die Meldung ausgegeben welche Exception (mit what()-Ausgabe) zu dem Abbruch führt. Dank diesem Verhalten habe ich schon öfters fehlende "catch"-Blöcke finden können.
Jetzt, nachdem du die Antwort von theta gelesen hast und vielleicht eine Alternative finden möchtest, wie du die fehlenden Catch-Blöcke finden kannst, sei noch dies gesagt:
1. Es gibt Programme, welche dies für dich prüfen können.
2. Man kann auch in dermainein globalestry-catchmachen. Wenn man zudem sein Design entsprechend anpasst, kann man trotz auftreten eines Fehlers in dermain, die Daten noch retten und sichern.
Ich habe sogar schon gesehen, wie jemand das Programm in dermaindann neugestartet hat mit den geretteten Daten. Also quasi: "Fataler Fehler, Daten gerettet, Log Eintrag erstellt, sie dürfen weiterarbeiten!"
Grüssli
-
Im Übrigen erklärt der kommende C++ Standard throw-Ausnahmespezifizierungen für "deprecated"! Sogar jedes
throw()wird in der Standardbibliothek durchnoexceptersetzt.Die Alternative wird dann so aussehen:
void f(int); // <-- kann Ausnahme werfen void g(int) noexcept; // <-- wirft keine Ausnahme void h(int) noexcept(true); // <-- wirft keine Ausnahme void k(int) noexcept(false); // <-- kann Ausnahme werfen...wobei die Doppelverneinung im letzten Fall etwas gewöhnungsbedürftig ist.

Darüberhinaus wird
noexceptein Compile-Zeit-Operator sein, mit dem man Ausdrücke darauf überprüfen kann, ob sie garantiert keine Ausnahme werfen können:bool nx_f = noexcept( f(23) ); // false bool nx_g = noexcept( g(42) ); // false oder true bool nx_h = noexcept( h(17) ); // false oder true bool nx_k = noexcept( k(29) ); // falseMit anderen Worten: Der noexcept-Operator darf pessimistisch sein und immer false zurückgeben. Der Compilerhersteller sollte sich aber hier Mühe geben und die noexcept-Spezifikation beachten. Wenn der Operator true liefert, wirft der Ausdruck garantiert keine Ausnahme.
kk
-
Dravere schrieb:
2. Man kann auch in der
mainein globalestry-catchmachen.Und genau das führt dazu, dass freeorion auf meinem Rechner mit "main() caught exception(std::exception): unregistered class" nicht aussteigt, sondern endlos in der Event-Schleife weiterläuft. Mit dieser Meldung wird niemand jemals den Fehler finden ohne im geistigen "Single-Step-Modus" durchlatschen zu müssen.
Aber zurück zum Thema, ich kenne Sutter. Ich habe trotzdem mal den Inhalt hinter dem Link oben überflogen, und eine Sache ist Bemerkenswert:
Sutter schrieb:
Here’s what many people think that exception specifications do:
- Guarantee that functions will only throw listed exceptions (possibly none).
- Enable compiler optimizations based on the knowledge that only listed exceptions (possibly none) will be thrown.
Da habt Ihr natürlich Recht, wer von einer dieser beiden (oder von beiden) Annahmen ausgeht, liegt falsch und wird auf Probleme stoßen.
(Siehe Ralf Schneeweiß, Moderne C++-Programmierung, Seite 162ff)
Aber:Sutter schrieb:
The above expectations are, again, deceptively close to being correct. Consider again the code in Example 1(b):
// Example 1(b) reprise, and two // potential white lies: // int Gunc() throw(); // will throw nothing (?) int Hunc() throw(A,B); // can only throw A or B (?)Are the comments correct? Not quite. Gunc() may indeed throw something, and Hunc() may well throw something other than A or B! The compiler just guarantees to beat them senseless if they do… oh, and to beat your program senseless too, most of the time.
Und wenn ich, wie in meinem Post oben beschrieben, genau _dieses_ Verhalten haben möchte? Wenn ich erzwingen möchte das "hunc()" sich auch wirklich um alle Ausnahmen außer A und B selber kümmern _muss_? Dann kann ich mit der obigen Spezifikation dafür sorgen, dass entweder der Compiler und/oder das am ende stehende Programm mir sinnvoll (nicht sinnvoll siehe oben mit dem all-in-one-catch) um die Ohren fliegt.
Also zurück zur Frage: Warum ist das nutzlos?
Es erscheint mir eher, dass es wie bei vielen Details in C++ ist, es kommt auf das Wissen an, was geschieht.
Spätestens wenn man an einem Toolkit oder Framework arbeitet ist das schon wichtig, dass die Nutzer sich auf die per Ausnahmespezifikation getätigten Aussagen verlassen können. Auch ein Kommentar hilft da nicht weiter. Aber ein brutales terminate() im Testprogramm wird den Autoren des Übeltäters wohl eher zum Überarbeiten anregen, als eine nichtssagende, wer-weiß-woher stammende ::std::exception in einem Fehlerbericht.

Abhängigkeiten und externe Programme würde ein ToolKit-/FrameWork-/Bibliotheks-Programmierer ja sicher vermeiden wollen, gell?

@Krümelkacker:
Der kommende C++-Standard fühlt sich fast schon wie Perl6 oder Duke Nukem forever an. Diskutiert/gearbeitet wird daran seit gefühlten Äonen, aber zumindest im gcc-4.4.4, den ich nutze gilt nach wie vor:#ifndef __GXX_EXPERIMENTAL_CXX0X__ # include <c++0x_warning.h>
(Aber ich freue mich darauf wenn das ein Ende hat...)Gerade im Hinblick auf das Exception-Handling, und der Verschiebung in die Kompilierzeit blicke ich dem sehr positiv entgegen. Denn eine solche Überprüfung ist natürlich um ein Vielfaches sinnvoller und gewinnbringender als ein terminate()-Abbruch eines laufenden Programms.
P.S.: Ich frage mich gerade, ob es sinnvoll ist das ToolKit, an dem ich gerade arbeite, schon heute nach C++0x zu "portieren" ("aufbohren" triffts wohl eher)... Was meint Ihr? Immerhin müsste dann jeder Nutzer mit "-std=c++0x" kompilieren.
Edith hat anzumerken: Erst im März 2011 soll C++0x Draft abgeschlossen sein, und WG21 (http://www.open-std.org/jtc1/sc22/wg21/) geht laut wikipedia davon aus, dass es bis zum ISO Standard nochmal sechs bis 12 Monate dauert. Ich glaube C++0x ist (noch) keine Option.
-
Yamakuzure schrieb:
Dravere schrieb:
2. Man kann auch in der
mainein globalestry-catchmachen.Und genau das führt dazu, dass freeorion auf meinem Rechner mit "main() caught exception(std::exception): unregistered class" nicht aussteigt, sondern endlos in der Event-Schleife weiterläuft. Mit dieser Meldung wird niemand jemals den Fehler finden ohne im geistigen "Single-Step-Modus" durchlatschen zu müssen.
Tja, auch beim Werfen von Exceptions gilt es sinnvolle Informationen mitzuliefern. Oh Wunder, man könnte sogar Zeilennummer und File-Namen mitwerfen. Siehe die Makros
__FILE__und__LINE__.Yamakuzure schrieb:
Und wenn ich, wie in meinem Post oben beschrieben, genau _dieses_ Verhalten haben möchte? Wenn ich erzwingen möchte das "hunc()" sich auch wirklich um alle Ausnahmen außer A und B selber kümmern _muss_? Dann kann ich mit der obigen Spezifikation dafür sorgen, dass entweder der Compiler und/oder das am ende stehende Programm mir sinnvoll (nicht sinnvoll siehe oben mit dem all-in-one-catch) um die Ohren fliegt.
Du willst ein Verhalten, welches nicht mal garantiert ist? Siehe den letzten Teil:
The compiler just guarantees to beat them senseless if they do… oh, and to beat your program senseless too, most of the time.
Zum Beispiel ignoriert der MSVC die Dinger rigoros

Zudem ist auch keine Garantie vorhanden, welche Informationen du von einemterminateerhälst. Das kann grundsätzlich auch einfach so lauten: "The program terminated." Eine Menge an Informationen, muss ich schon sagen
Yamakuzure schrieb:
Der kommende C++-Standard fühlt sich fast schon wie Perl6 oder Duke Nukem forever an. Diskutiert/gearbeitet wird daran seit gefühlten Äonen, ...
Leicht übertrieben. Der letzte Standard war von 2003. Im 2006 kam der TR1 heraus. Und wie es aktuell aussieht, wird Ende 2011 der neue C++ Standard von der ISO veröffentlicht werden.
Grüssli
-
Dravere schrieb:
Yamakuzure schrieb:
Dravere schrieb:
2. Man kann auch in der
mainein globalestry-catchmachen.Und genau das führt dazu, dass freeorion auf meinem Rechner mit "main() caught exception(std::exception): unregistered class" nicht aussteigt, sondern endlos in der Event-Schleife weiterläuft. Mit dieser Meldung wird niemand jemals den Fehler finden ohne im geistigen "Single-Step-Modus" durchlatschen zu müssen.
Tja, auch beim Werfen von Exceptions gilt es sinnvolle Informationen mitzuliefern. Oh Wunder, man könnte sogar Zeilennummer und File-Namen mitwerfen. Siehe die Makros
__FILE__und__LINE__.Okay, Missverständnis: Ich habe mit der Entwicklung von freeorion nichts zu tun. Und meine Exceptions halten sich an das Muster, dass in der PDFLib verwendet wird, also nicht nur "was", sondern auch "woher". Wäre der Kram auf meinem Mist gewachsen, würde die Ausgabe ungefähr so lauten:
"main() caught exception(pwx::mrf::ExceptionBase): [TMemRing->isValueIn()] Data not found" ... Genau das hatte ich gestern Abend, und die Methode isValueIn() hat nur fünf Zeilen, von denen nur eine werfen kann, und die war auch Schuld.Dravere schrieb:
Du willst ein Verhalten, welches nicht mal garantiert ist?
Nein, ich möchte mich selbst zwingen nur das auszuliefern, was tut wie geheißen. Wenn ich eine Methode mit "throw()" angebe, dann darf diese auch wirklich nichts werfen. Mache ich bei der Umsetzung etwas falsch, soll es knallen, und nicht Unsinn über ein main-catch ausgegeben werden. (Und da ich mit gcc schreibe und teste kann mir das verhalten des MSVC egal sein. Zum Glück. ;))
Draveres schrieb:
Zudem ist auch keine Garantie vorhanden, welche Informationen du von einem
terminateerhälst. Das kann grundsätzlich auch einfach so lauten: "The program terminated." Eine Menge an Informationen, muss ich schon sagen
Auf meinem System, das für die Entwicklung zählt, ist es zum Glück anders, sonst würde ich es nicht so machen.
Draveres schrieb:
Leicht übertrieben. Der letzte Standard war von 2003. Im 2006 kam der TR1 heraus. Und wie es aktuell aussieht, wird Ende 2011 der neue C++ Standard von der ISO veröffentlicht werden.
Oder Anfang 2012, wie ich schrieb, fals du meinen Edit noch gesehen hast. Ich habe hier auch nicht nur absichtlich, sondern sehr rigoros übertrieben, und nicht nur leicht.

Wie dem auch sei, das Gefrickel mit den Ausnahmespezifizierern tue ich mir auch wirklich nur aus den oben genannten Gründen an. Es gibt nämlich noch einen Nachteil: Die Funktionsliste von Code::Blocks findet keine Funktion, die einen Ausnahmespezifikation hat. Sehr nervig!
-
Wieso ist es besser, wenn es über
terminateknallt oder in der main-Funktion tut? Du kannst ja, wenn du unbedingt willst, während der Entwicklung im Catch-Block in dermainselber einterminateaufrufen. Oder wie ich es für sehr viel sinnvoller halte, während der Entwicklung im Debug-Modus laufen lassen und den Code anhalten lassen, wenn eine unbehandelte Ausnahme auftritt. Dann siehst du auch schön den Callstack und je nach Debugger sogar die Werte.Und es ist sehr schön, wenn es auf deinem System so läuft. Je nach Verwendung und Grösse deines Projektes, wird es aber nicht bei deinem System bleiben. Ein Code kann auch mal auf einen anderen Kompiler portiert werden. Wenn du OpenSource entwickelst, dann sowieso.
Es gibt so viele Nachteile bei der Ausnahmespezifikation (du listest sogar zusätzlich auf!) und gäbe so viele bessere Methoden, das gleiche zu erreichen, was du über die Ausnahmespezifikation erreichst, ohne all diese Nachteile ... wieso machst du es dann immernoch über die Ausnahmespezifikation?

Grüssli
-
Irgendwie ist es schwierig das zu beschreiben.
Also ich versuche das mal anhand eines Falles, den ich vorgestern hatte, wo die Spezifikation mit terminate() ein Glücksfall war:
Eine Methode setzt einen internen Zeiger auf ein Element einer doppelt verketten Liste, und tut dieses je nach Index, der übergeben wird. Die übergebene Zahl wird vorher normalisiert, so dass sie auf jeden Fall "0 <= index < size()" ist.
Die benannte Methode schlägt niemals fehl, es sei denn, es gibt keine Elemente. In diesem Fall wirft sie eine spezielle Ausnahme, die nur von dieser einen Methode geworfen werden kann.
Ich habe eine andere Methode mit throw() markiert. Diese sollte überprüfen, ob es in der Liste ein per Argument übergebenes Element gibt. (Ein kleiner Vorgriff: Ich hatte in genau dieser Methode vergessen den Fall, dass die Liste leer ist, abzufangen. Da dieser Fall aber abgefangen hätte werden müssen, hatte ich auf einen try-catch-Block verzichtet.) Diese Methode geht nun die Liste durch, und muss dafür jedes Element bis zum Ende, oder bis zu einem Treffer überprüfen. Hierfür wird die oben beschriebene Methode in einer Schleife verwendet.Mit der Technik des globalen try-catch-Blocks (den ich übrigens auch verwende) hätte ich nur die Aussage erhalten, das eine Ausnahme vom Typ der abgefangen Klasse (Im Zweifelsfall std::exception) aufgetreten ist. Der Nutzen wäre gleich null gewesen. Diese Ausnahme kommt immer aus der gleichen Methode, keine sonstwie übergebenen Informationen hätte irgendeine Hilfe sein können.
Mit der terminate()-Methode hatte ich dagegen genau zwei Aussagen:
1.: Es handelt sich um genau diese spezielle Ausnahme, von wo die geworfen wird, war mir als Entwickler natürlich aufgrund ihrer Natur klar.
2.: Die Ausnahme trat an einer Stelle auf, wo sie nicht auftreten durfte.Nun handelt es sich bei dem Programm um ein Testprogramm für eben dieses zu entwickelnde Toolkit. Und wie das bei Testprogrammen so üblich ist (sein sollte), hat es natürlich vor dem Abbruch genau angemerkt, was geschehen soll.
So war es für mich ein Leichtes den Fehler zu finden, denn der einzige "Übeltäter" konnte die mit throw() markierte Methode sein, die es natürlich auch war.
Am Ende wird es nicht mehr zu einem terminate() kommen können. Zum Einen weil das Testprogramm mir ermöglichen soll alle "Störstellen" zu finden, zum Anderen weil die Ausnahmespezifikationen am Ende wieder entfernt werden.--- cut ---
Es handelt sich hierbei, _natürlich_, um einen Sonderfall. Ich versuche auch nicht irgendwem weißzumachen, das Ausnahmespezifikation was ganz Tolles wären. Sind sie nicht. Bei einer normalen Applikation würde ich sie eher vermeiden wollen, da sie die Flexibilität einschränken.
Es geht mir nur darum, dass es gerade bei einer so vielfältigen Sprache wie C++ eher ungünstig ist, solche Pauschalaussagen wie "Ist nutzlos" zu tätigen. Vor allem wenn ich den Gegenbeweis "Bunt auf weiß" in meiner IDE vor Augen habe.
Zusätzlich habe ich mit dem FreeOrion-Beispiel auch noch den Gegenbeweis zu "du brauchst nur catch in main()", diesmal "weiß auf schwarz".
-
Yamakuzure schrieb:
Mit der Technik des globalen try-catch-Blocks (den ich übrigens auch verwende) hätte ich nur die Aussage erhalten, das eine Ausnahme vom Typ der abgefangen Klasse (Im Zweifelsfall std::exception) aufgetreten ist. Der Nutzen wäre gleich null gewesen. Diese Ausnahme kommt immer aus der gleichen Methode, keine sonstwie übergebenen Informationen hätte irgendeine Hilfe sein können.
1. Wenn du nützliche Informationen in der Exception verpacken würdest, hätte es durchaus einen Mehrwert gehabt. Man muss ja nicht nur ein
catch(...)durchführen in der main. Man kann ja auch die zahllosen verschiedenen Basis-Exception abfangen, welche man verwendet oder sogar ganz anderes zeug. Wenn also sinnvolle Informationen in der Exception vorhanden wären, hättest du auch die nötigen Informationen in der main gehabt.
2. Ein Debugger hätte dir diese Informationen sofort geliefert und gerade dazu sind Debugger auch da.Yamakuzure schrieb:
Es geht mir nur darum, dass es gerade bei einer so vielfältigen Sprache wie C++ eher ungünstig ist, solche Pauschalaussagen wie "Ist nutzlos" zu tätigen. Vor allem wenn ich den Gegenbeweis "Bunt auf weiß" in meiner IDE vor Augen habe.
Ausnahmespezifikationen sind in der aktuellen Form ziemlich nutzlos. Nicht ohne Grund nimmt man sie aus dem Standard raus. Ich kann mich nur wiederholen, es gibt deutlich besser Alternativen, für das was du erreichen möchtest.
Yamakuzure schrieb:
Zusätzlich habe ich mit dem FreeOrion-Beispiel auch noch den Gegenbeweis zu "du brauchst nur catch in main()", diesmal "weiß auf schwarz".
Das ist doch kein Gegenbeweis. Das ist nur ein Beweis, dass ihre Fehlermeldungen schlecht sind und allenfalls die mitgelieferten Fehlerinformationen.
Grüssli
-
Zu 1.:
Du liest den Text nicht. _Meine_ exceptions tragen die Informationen was _wo_ passiert ist mit.(*) In dem Beispiel hätte diese Information aber nur ausgesagt, was ich eh schon wusste, da genau diese Exception an nur einer einzigen Stelle vorkommt. Aber die Methode, die diese Ausnahme nicht abgefangen hat, was ein Fehler war, hätte sie unbedingt abfangen _müssen_, da diese spezielle Methode _niemals_ fehlschlagen darf. Ich musste aber nicht herausfinden _das_ eine Ausnahme aufgetreten ist, sondern _wo_ sie _nicht_ aufgefangen wurde.Und in main() steht:
try { /* alle möglichen tests */ } catch (pwx::mrf::ExceptionBase &e) { /* info handling */ } catch (std::exception &e) { /* sonstige exception infos */ } catch (...) { /* Panik! */ }(*) Gespeichert wird: Objektname, Methodenname, Datei, Zeile, Beschreibung, relevante Daten. Aber das reicht nun einmal nicht immer.
Zu 2.: Ja, ich weiß. Ich verwende gdb sehr intensiv, da er sehr gut in Code::Blocks integriert ist.
Zum "Gegenbeweis": Es ist der Beweis dafür, dass die Pauschalaussage, das try-catch in main() alle Probleme pauschal löst, falsch ist. Man muss schon ein wenig mehr tun, wie du selber ja sagst, gell?

-
theta schrieb:
Herb Sutter im C++ Users Journal zu Exception Specifications:
http://www.gotw.ca/publications/mill22.htmAuch wenn ich Herb Sutters Ausführungen zu C++ als sehr hochwertig betrachte, ist dies in Bezug auf Exceptions definitiv nicht der Fall. Es gibt in C++ keinerlei logischen Grund einen Destruktor nicht als throw() zu definieren, da Exception werfende Destruktoren unweigerlich zu Problemen führen, und früher oder später eine zweite Exception geworfen wird -> terminate(). Da aber in Falle eines werfenden Destruktors das ganze nicht mehr deterministisch passiert, ist der Fehler faktisch schwer zu finden. Daher sollten Destruktoren immer throw() definiert sein.
Es kann doch nicht sein, daß man eine Programmsprache nach den mangelhaften Compiler entwirft. Wenn der Compiler kaputt ist, sollte man ihn reparieren und nicht die Sprache an den kaputten Compiler anpassen.
-
Yamakuzure schrieb:
Du liest den Text nicht.
Doch, tue ich. Ich möchte dich also bitten, wenn ich mir schon die Zeit nehme, deine Beiträge durchzulesen, dass du mir nicht unterstellst, dass ich dies nicht tue. Ich habe einfach deinen Text missverstanden. Wahrscheinlich weil er etwas komplex ist, um einen simplen Sachverhalt zu erklären.
Man hätte nämlich sagen können, dass bei einem globalen
try-catchin dermain, der Callstack fehlt. Das ist grundsätzlich schon alles, was du kritisierst. Aber wie gesagt, dazu gäbe es ja den Debugger.Aber den benutzt du ja anscheinend auch:
Yamakuzure schrieb:
Zu 2.: Ja, ich weiß. Ich verwende gdb sehr intensiv, da er sehr gut in Code::Blocks integriert ist.
Dann frage ich mich immer noch, wieso du die
throw-Spezifikation verwendest. Mit dem Debugger hättest du diese Informationen schliesslich auch problemlos erhalten.Yamakuzure schrieb:
Zum "Gegenbeweis": Es ist der Beweis dafür, dass die Pauschalaussage, das try-catch in main() alle Probleme pauschal löst, falsch ist. Man muss schon ein wenig mehr tun, wie du selber ja sagst, gell?

Ich habe dies so nicht gesagt. Nicht mal annähernd. Ich wollte eine Alternative Vorschlagen, welche in vielen Fällen sehr praktisch sein kann. Als eine pauschale Lösung für alle Probleme, habe ich dies nie beworben.
Grüssli