welche vorteile bietet c++ gegenüber c



  • freigeist3 schrieb:

    Eisflamme schrieb:

    Und dass man schneller zu einem Ergebnis kommt, liegt wohl auch einfach nur darin begründet, dass man in C weniger Konzepte verstehen muss.

    Ja, aber viele moderne C++ Experten verstehen ja nichtmal diese grundlegenden
    (prozeduralen) Konzepte, weil sie von den 'modernen' Lehrbüchern sofort ins
    kalte C++ Wasser geworfen werden, wo der Tanz (OOP, Templates) vor dem
    aufrechten Gang (Schleifen, Funktionen) gelehrt wird, also kurzerhand jene
    Teilmenge von C++, die über C hinaus geht, falscher Weise zuerst durchgenommen
    wird. Braucht man ja nur ins C++ Unterforum gucken, wo die Leute zwar brav
    mit <vector>, <boost> usw. arbeiten, aber so ihre liebe Not mit dem Vertauschen
    von Variablenwerten oder dem Finden einzelner Zeichen in einem String
    haben, also wo die elementarsten Operationen zum Problem werden.
    Also mich wundert's angesichts dieses Umstands kaum, dass moderne C++ Software
    typischer Weise erst nach dem 1000. Bugfix halbwegs das tut, was sie soll:
    Weil die Entwickler ja oft C++ vor (und nicht selten sogar anstelle)
    des eigentlichen Programmierens (aka algorithmisches Denken)
    gelernt haben.

    @volkard
    Mein Freund ist mittlerweile dazu übergegangen, mehrere Funktionen meiner
    C-Engine für seine C++ Engine zu wrappen und auf dieser Basis weiter zu
    arbeiten (was übrigens sowieso die typische Vorgangsweise in C++ zu sein
    scheint: Bereits existierende, gut implementierte C-Funktionen/Module neu zu
    'verkleiden' und das Resultat dann als coole C++ Lösung zu bezeichnen.
    Das fängt schon alleine damit an, dass man sich dutzende neue Namen für
    den elementaren Zuweisungsoperator ausdenkt:
    Klassen-Getter() und Setter() - und sich dann einredet, man hätte ebenso viele Funktionen 'neu' erfunden, wie man Getter und Setter hat.
    Was für eine Errungenschaft! Diese coole Kapselung von Klassen-Members ist
    ja schon ein Beispiel für die generelle C++ Tendenz, die elementarsten Räder
    auf zigfache Weise immer wieder auf's neue zu erfinden, neu zu benennen, und
    insgesamt nicht recht viel mehr zuwege zu bringen als sich neue Namen für
    allerlei - bereits existierende - Funktionen auszudenken.
    Die sinnvolle Kombination elementarer Operationen (Zuweisung z.B.)
    zu zunehmend komplexeren Prozeduren und Funktionen ist ja veraltet und hat
    in C++ nix verloren, hehe. Dazu wird's wohl noch für geraume Zeit so naive
    C-Arbeiter geben müssen, damit die C++ Leutchen was haben, das sie in ihre
    Klassen verpacken können.
    mfg

    Soviel Ahnung vom Programmieren wie Du hatte ich nach sechs Wochen. Du bist einfach noch nicht so weit, mitzureden.



  • Du

    Mein Freund ist mittlerweile dazu übergegangen, mehrere Funktionen meiner
    C-Engine für seine C++ Engine zu wrappen und auf dieser Basis weiter zu
    arbeiten (was übrigens sowieso die typische Vorgangsweise in C++ zu sein
    scheint: Bereits existierende, gut implementierte C-Funktionen/Module neu zu
    'verkleiden' und das Resultat dann als coole C++ Lösung zu bezeichnen.

    bist

    Das fängt schon alleine damit an, dass man sich dutzende neue Namen für
    den elementaren Zuweisungsoperator ausdenkt:
    Klassen-Getter() und Setter() - und sich dann einredet, man hätte ebenso viele Funktionen 'neu' erfunden, wie man Getter und Setter hat.
    Was für eine Errungenschaft!

    so was von

    Diese coole Kapselung von Klassen-Members ist
    ja schon ein Beispiel für die generelle C++ Tendenz, die elementarsten Räder
    auf zigfache Weise immer wieder auf's neue zu erfinden, neu zu benennen, und
    insgesamt nicht recht viel mehr zuwege zu bringen als sich neue Namen für
    allerlei - bereits existierende - Funktionen auszudenken.

    raus. 😃



  • Decimad schrieb:

    Inwiefern vereinfacht mir denn nun eine Exception das Freilassen aller nicht zwingend benötigten (Beispielsweise Caches) GDI-Ressourcen um es nochmal zu probieren?

    Beim Stack-Unwinding werden Destruktoren aufgerufen. Wenn Du dem Catcher sagen willst, er soll es in ein paar Sekunden nochmal probieren, kannste ihm auch sagen, daß er Caches löschen soll.
    Aber mir hätte es schon gereicht, die Daten ohne weitere Anzeige zu speichern, eventuelle Datenbankverbindungen zu schließen, Datei-Locks freizugeben, den Video-Modus zurückzusetzen, Netzwerkverbindungen zu trennen, ganz einfache Sachen, die ganz lästig sind, wenn man sie nicht macht.



  • Das Guttenberg unter den Programmen sozusagen, der geordnete Abgang! Nee, das sehe ich 1:1 ein, das ist okay. Ob man mit der GDI Probleme bekommt, oder dem Speicher, liegt ja auch bei fehlerfreiem Programmablauf oft nicht in der eigenen Hand. Aber diese ganzen DivisionByZero-Exceptions in den Algorithmen usw. kann ich eben nicht so ganz nachvollziehen.



  • volkard schrieb:

    Decimad schrieb:

    Inwiefern vereinfacht mir denn nun eine Exception das Freilassen aller nicht zwingend benötigten (Beispielsweise Caches) GDI-Ressourcen um es nochmal zu probieren?

    Beim Stack-Unwinding werden Destruktoren aufgerufen.

    Hmm, sind das nicht die Destuktoren, die selbst keine Exceptions werfen sollten? Weil wenn Sie das tun, undefiniertes Verhalten auftritt bzw. die Desktruktion einer Objekthierarchie kaputt geht? Also wäre es eigentlich sinnvoll eine "public: void ReleaseResources()"-Methode zu machen, damit man im Fall einer Exception beim Freigeben von Ressourcen noch handeln kann. Wer ruft die optimalerweise auf? Der Destruktor der Klasse? Der müsste dann die Exception schlucken, wenn er sie nicht behandeln kann. Unschön. Oder doch Clientcode? Dann geben wir das Schicksal in externe Hände.



  • Decimad schrieb:

    Aber diese ganzen DivisionByZero-Exceptions in den Algorithmen usw. kann ich eben nicht so ganz nachvollziehen.

    Viele libs werfen grotesk viele Exceptions. Das kann man in Java machen. In C++ sollte man sie sparsam einsetzen.
    Zum Beispiel eineEmptyStackException wäre in Java Katastrophe.

    Eine DivisionByZero kann Sinn ergeben, zum Beispiel wenn der Matrizeninvertierer mitten im Rechnen feststllt, daß sie nicht invertierbar war. Ich könnte auch stur weiterrechnen, aber dann müßte ich nachher nochmal über die ganze Matrix laufen und schauen, daß nirgend NAN oder INF aufgetaucht ist.

    Oder die Invertierfunktion gibt irgendwie anders zurück, ob's geklappt hat. Zusätzlicher Parameter oder zwei Rückgaben? Nicht hübsch. Das Matrixformat ändern, daß sie auch sowas wie NAN darstellen kann. Hmm, wenn es angemessen ist, mag es einen Versuch wert sein. Aber hier tendiere ich eher zu Exception, klingt einfach schneller als überall mit if zu hantieren und zu prüfen. Und in Zusammenhängen, wo es fast immer klappt, kann ich hübsch die Füße hochlegen und nur in der main() fangen, und trotzdem geht mir kein Rechenfehler durch die Lappen.



  • Ich versteh gerade nicht, wieso irgend ein dtor sowieso eine Exception werfen können sollte. Das würde ich aus der Problematik heraus gar nicht erst erlauben. Wenn irgendwas nicht gelöscht werden kann, dann ist das eben Pech und wird evtl. noch irgendwo reingeschrieben (und wenn die entsprechende Datei nicht geöffnet wird, dann eben auch da nicht). Wenn ein dtor seinen Speicher nicht freigeben kann, wie will man so etwas denn sinnvoll behandeln? Das kann dann ja die Runtime bzw. das BS übernehmen...

    Darf im Stack-Unwinding-Prozess eigentlich auch keine Ausnahme lokal erzeugt und gefangen werden? Sodass im dtor try{bla}catch(...){} steht? Dafür sähe ich gewisse Anwendung, wenn so was eben Mal passieren kann. Oder geht das auch nicht?



  • GPC schrieb:

    Hmm, sind das nicht die Destuktoren, die selbst keine Exceptions werfen sollten?

    Das sind die Fälle, wo meine Programme fehlerhaft sind. Also Platte zu 100% voll => es wird bei kritischem Fehler nicht mehr korrekt gespeichert UND der Benutzer sieht es nicht. Er würde keine Messagebox bekommen, wenn die Datenbankverbindung oder andere Netzwerkverbindung nicht geschlossen werden könnte oder der Videomodus nicht zurückgesetzt werden könnte. Das hat mich noch nicht genervt.

    GPC schrieb:

    void ReleaseResources()

    Nein, die heilt gar nichts.

    GPC schrieb:

    Oder doch Clientcode? Dann geben wir das Schicksal in externe Hände.

    Ich weiß nicht, was hiermit gemeint ist.



  • volkard schrieb:

    GPC schrieb:

    Hmm, sind das nicht die Destuktoren, die selbst keine Exceptions werfen sollten?

    Das sind die Fälle, wo meine Programme fehlerhaft sind. Also Platte zu 100% voll => es wird bei kritischem Fehler nicht mehr korrekt gespeichert UND der Benutzer sieht es nicht. Er würde keine Messagebox bekommen, wenn die Datenbankverbindung oder andere Netzwerkverbindung nicht geschlossen werden könnte oder der Videomodus nicht zurückgesetzt werden könnte. Das hat mich noch nicht genervt.

    Im Endeffekt heißt das einfach, dass dann halt business as usual gemacht wird, wenn der Destruktor Ressourcen nicht korrekt freigeben konnte? 🙂
    Bzw. sich das Problem dahingehend ausdehnt, dass man in Destruktoren keine Funktionen aufrufen sollte, die eine Exception werfen könnte.

    GPC schrieb:

    void ReleaseResources()

    Nein, die heilt gar nichts.

    Offensichtlich kann man sich auf Destruktoren aber auch nicht verlassen.

    GPC schrieb:

    Oder doch Clientcode? Dann geben wir das Schicksal in externe Hände.

    Ich weiß nicht, was hiermit gemeint ist.

    Dass der Code, der deine Klasse benutzt, dafür verantwortlich ist, dass auch Exceptions in solchen Release-Methoden gehandelt wird, da der Destruktor es nicht kann.

    Durch das Stack-Unwinding geht btw. auch der Call stack verloren 👍



  • GPC schrieb:

    Im Endeffekt heißt das einfach, dass dann halt business as usual gemacht wird, wenn der Destruktor Ressourcen nicht korrekt freigeben konnte? 🙂
    Bzw. sich das Problem dahingehend ausdehnt, dass man in Destruktoren keine Funktionen aufrufen sollte, die eine Exception werfen könnte.

    Ja.



  • GPC schrieb:

    Im Endeffekt heißt das einfach, dass dann halt business as usual gemacht wird, wenn der Destruktor Ressourcen nicht korrekt freigeben konnte? 🙂
    Bzw. sich das Problem dahingehend ausdehnt, dass man in Destruktoren keine Funktionen aufrufen sollte, die eine Exception werfen könnte.

    Im Destruktor selbst kann man durchaus Funktionen aufrufen, die Exceptions werfen, diese sollten aber noch im Destruktor abgefangen werden. Wobei es noch immer die Möglichkeit gibt, das ganze in einem Logfile zu protokollieren (wenn möglich).



  • Im Endeffekt heißt das einfach, dass dann halt business as usual gemacht wird, wenn der Destruktor Ressourcen nicht korrekt freigeben konnte? 🙂
    Bzw. sich das Problem dahingehend ausdehnt, dass man in Destruktoren keine Funktionen aufrufen sollte, die eine Exception werfen könnte.

    Was willst du denn jetzt damit überhaupt sagen?
    Wenn tatsächlich die im Konstruktor angeforderten Ressourcen nicht mehr freigegeben werden können, hat man sowieso ein ziemlich großes Problem, das nicht vom Programm abgefangen werden kann.
    Könntest du ein Beispiel geben, bei dem das relevant wäre?



  • Aber mal eine andere Frage, wer garantiert einem eigentlich, dass durch das Zerstören und das Stackunwinding nicht eventuell noch viel größerer Schaden angerichtet wird, wenn dort als Folgefehler noch etwas katastrophales passiert?^^ Zumeist muss man sich die Fälle, in denen das auftritt sowieso erstmal künstlich theoretisch konstruieren, und um da einen schlüssigen Beweis für die Überlegenheit zu finden, muss man das wahrscheinlich sogar noch gründlich tun! 😃



  • dass durch das Zerstören und das Stackunwinding nicht eventuell noch viel größerer Schaden angerichtet wird, wenn dort als Folgefehler noch etwas katastrophales passiert?^^

    Was denn für Folgefehler? Solange Destruktoren nicht werfen, gibt es auch keine Folgefehler.



  • Decimad schrieb:

    Aber mal eine andere Frage, wer garantiert einem eigentlich, dass durch das Zerstören und das Stackunwinding nicht eventuell noch viel größerer Schaden angerichtet wird, wenn dort als Folgefehler noch etwas katastrophales passiert?^^

    Keiner. Aber ich kann mir gerade nicht vorstellen, wie man eine Katastrophe dadurch herbeiführen könnte (außer mal system("echo j|format e: /V:haha") an passende Stelle zu schreiben.)



  • Das erschließt sich mir jetzt noch nicht so ganz irgendwie... (Gemeint ist hier nicht etwa irgendwer, sondern Irgendwer! ...ich sollte öfter zitieren!)



  • Decimad schrieb:

    Aber mal eine andere Frage, wer garantiert einem eigentlich, dass durch das Zerstören und das Stackunwinding nicht eventuell noch viel größerer Schaden angerichtet wird, wenn dort als Folgefehler noch etwas katastrophales passiert?^^ Zumeist muss man sich die Fälle, in denen das auftritt sowieso erstmal künstlich theoretisch konstruieren, und um da einen schlüssigen Beweis für die Überlegenheit zu finden, muss man das wahrscheinlich sogar noch gründlich tun! 😃

    Wer garantiert, dass ein Funktionsaufruf fehlerfrei verläuft? Oder eine Zuweisung? Das sind Fehler die das Programm selbst nicht behandeln kann. Und wenn selbst solche einfachen Operationen scheitern ist das Programm (evt. sogar das Betriebssystem) zum Absturz verurteilt ^^.



  • Also die Sache ist die, meine Programme sind ja nun schon von vornherein erstmal als fehlerlos zu betrachten, aber ich sehe mich nicht in der Annahme gestärkt, ausgerechnet in dem Fall, in dem das OS mein Programm am fehlerfreinen Fortbestand hindert, darauf zu vertrauen, dass es nicht noch viel schlimmeres tut!



  • Wenn das OS abstürzt kann dein Programm gar nichts mehr machen.



  • aber ich sehe mich nicht in der Annahme gestärkt, ausgerechnet in dem Fall, in dem das OS mein Programm am fehlerfreinen Fortbestand hindert, darauf zu vertrauen, dass es nicht noch viel schlimmeres tut!

    Wenn dein OS so böse Sachen macht, kannst du auch nichts mehr dafür.

    Wenn man mal von solchen Fällen absieht, ist RAII schon ein ziemlich gutes Idiom, das richtige Exceptionsicherheit in vielen Fällen erst ermöglicht.


Anmelden zum Antworten