Verleitet C++ zum komplizierteren denken?



  • ~john schrieb:

    Natürlich kann man das Programm auch anders formulieren, aber das paßt nun einmal nicht zu deiner Hypothese.

    ein paar eingestreute 'const' lassen sich genauso einfach untergraben:

    #include<iostream>
    
    using namespace std;
    
    class B {
    private:
        const char c;
    public:
        B() : c('b') {}
        const char* get() const { return &c; }
    };
    
    int main(){
        B b;
    
        const B *p;
    
        cout << "private const b.c ist '" << *b.get() << "'" << endl;
    
        p = &b;
        *(char*)p = 'z';
    
        cout << "und jetzt: '" << *b.get() << "'" << endl;
    }
    

    Ausgabe bei mir:

    private const b.c ist 'b'
    und jetzt: 'z'
    


  • audacia schrieb:

    Es hindert dich ja auch in Java oder C# niemand daran, dispose() mehrfach oder finalize() explizit aufzurufen.

    mag sein. Aber ein Destruktor, der seinen Namen verdient, sollte sich nicht beliebig oft auf ein- und dasselbe Objekt anwenden lassen - sonst ist er kein Destruktor, sondern eine gewöhnliche Methode.

    (eigentlich nicht einmal das, denn auch eine gewöhnliche Methode sollte sich nicht mehr aufrufen lassen, nachdem das Objekt angeblich destruiert worden ist.)



  • u-ser_l schrieb:

    ein paar eingestreute 'const' lassen sich genauso einfach untergraben:

    sieh es doch mal positiv. auch wenn's meistens nicht sinnvoll ist, aber in welcher sprache kann man noch solche tricks machen, ausser in C++?
    in c++ ist nun mal alles möglich, auch wenns schwierig ist und zu kompliziertem denken verleitet.
    btw, ja ich bin der echte fricky. ich darf ja auch mal was gutes über c++ äussern.
    🙂



  • //fricky schrieb:

    richtig, aber das sollte nicht darüber hinwegtäuschen, dass client-code mit casts usw. jede kapselung aufheben kann, wenn er will.

    Das geht über Reflection genauso in Java und C#.

    u_ser-l schrieb:

    audacia schrieb:

    Es hindert dich ja auch in Java oder C# niemand daran, dispose() mehrfach oder finalize() explizit aufzurufen.

    mag sein. Aber ein Destruktor, der seinen Namen verdient, sollte sich nicht beliebig oft auf ein- und dasselbe Objekt anwenden lassen - sonst ist er kein Destruktor, sondern eine gewöhnliche Methode.

    Unfug. Ungültige Funktionsaufrufe zur Übersetzungszeit zu verhindern ist schlichtweg nicht möglich. Und für die Fehlerdetektion zur Laufzeit gibt es Tools wie CodeGuard.



  • audacia schrieb:

    //fricky schrieb:

    richtig, aber das sollte nicht darüber hinwegtäuschen, dass client-code mit casts usw. jede kapselung aufheben kann, wenn er will.

    Das geht über Reflection genauso in Java und C#.

    reflection funzt zur laufzeit und ausserdem brauchste dafür die erlaubnis des security-managers. ist schon ein wenig anders. das argument von u_ser-l, dass OO in C++ nur ein 'namespace-feature' ist, ist nicht völlig unbegründet.
    🙂



  • ein paar eingestreute 'const' lassen sich genauso einfach untergraben:

    C++ ist keine Sprache, die dich zu irgendetwas zwingen will. Das ist aber auch das einzige, was du damit zeigst. Wichtig ist, dass sich das const nicht versehentlich austricksen lässt.
    Was das auf OOP wieder für einen Effekt haben soll musst du mir erst erklären, für mich ist objektorientierte Programmierung eine Programmierweise, ein Paradigma eben, eine rein objektorientierte Sprache eine Sprache die diese Programmierweise selbst in Sprachkonstrukten und Bibliotheken komplett durchzieht und eine objektorientierte Sprache eine Sprache, die Hilfestellungen zur objektorientierten Programmierung liegen.
    Objektorientierung ist Sache des Programmierers. Du kannst auch in Smalltalk auf OOP pfeiffen, wenn du Lust dazu hast..

    Du hättest deinen Spaß mit Python, die haben Datenkapselung durch Umbenennung der Member realisiert *huch* Trotzdem ist die Sprache objektorientiert 🙄

    Aber dein Beispiel btw.. ist meines Wissens undefiniertes Verhalten(es sei denn für Member gelten Sonderregeln), Zufall, dass dein Compiler das unterstützt. const lässt sich nur wegcasten, wenn das Ursprungsobjekt nicht const war.



  • JustAnotherNoob schrieb:

    Wichtig ist, dass sich das const nicht versehentlich austricksen lässt.

    ach was, irgendein wilder pointer, der unabsichtlich auf dein const-objekt zeigt und was reinschreibt. schon haste den salat.
    🙂



  • ach was, irgendein wilder pointer, der unabsichtlich auf dein const-objekt zeigt und was reinschreibt. schon haste den salat.

    Irgendwie geht doch alles. Zudem ist es dann wieder undefiniertes Verhalten. Du kannst einfach keine Konstante modifizieren, geht auch nicht mit Pointern.

    Dass Compiler da nicht unbedingt drauf prüfen lässt sich wohl auf den Mehraufwand zurückführen, evtl. sogar zur Laufzeit(mit dynamischen Libs vielleicht?) und dass es nicht wirklich eine übliche Fehlerquelle ist. Viele Überlegungen sind halt praktischer und nicht theoretischer Natur..



  • //fricky schrieb:

    JustAnotherNoob schrieb:

    Wichtig ist, dass sich das const nicht versehentlich austricksen lässt.

    ach was, irgendein wilder pointer, der unabsichtlich auf dein const-objekt zeigt und was reinschreibt. schon haste den salat.
    🙂

    Aber ich habe gar keine wilden pointer. Das war eher in C üblich, weshalb auch nur Du diese Gefahr überhaupt siehst.



  • Aber ich habe gar keine wilden pointer. Das war eher in C üblich, weshalb auch nur Du diese Gefahr überhaupt siehst.

    Richtig, hat schonmal jemand fricky über Punkt 1 aus "Effective C++" aufgeklärt?



  • volkard schrieb:

    Aber ich habe gar keine wilden pointer.

    Stell mal den Compiler auf "unleashed optimization", dann gehen deine Pointer richtig wild ab und dümpeln nicht nur so lahm rum. Bringt bis zu 36% mehr Speed. 👍



  • volkard schrieb:

    Aber ich habe gar keine wilden pointer. Das war eher in C üblich, weshalb auch nur Du diese Gefahr überhaupt siehst.

    ok, dann verzichten wir eben auf pointer in unserem c++ programm und nehmen einen falschen array-index um unser const-objekt zu zersemmeln. du kannst es drehen wie du willst, in einer 'unmanaged' umgebung und einer programmiersprache die auf rohem speicher arbeitet, können solche bugs immer passieren.

    JustAnotherNoob schrieb:

    Richtig, hat schonmal jemand fricky über Punkt 1 aus "Effective C++" aufgeklärt?

    was steht denn da? bestimmt sowas wie: mach das nicht, lass dieses, um himmels willen nein!, gefährlich, pass auf, usw...
    🙂



  • //fricky schrieb:

    volkard schrieb:

    Aber ich habe gar keine wilden pointer. Das war eher in C üblich, weshalb auch nur Du diese Gefahr überhaupt siehst.

    ok, dann verzichten wir eben auf pointer in unserem c++ programm und nehmen einen falschen array-index um unser const-objekt zu zersemmeln.

    Was läßt Dich annehmen, daß ich Arrays benutze, die Indexgrenzüberschreitungen zulassen?
    Es wird nicht funktionieren, mit Deinem Gefrickel in C stichhaltige Argumente gegen C++ zu sammeln. Man hat sich nämlich Gedanken gemacht, wie man in C++ die bösesten Fallstricke von C entschärft.



  • Mit anderen Worten: Man nimmt was frickeliges als Basis und versucht das grundlegende Konzept irgendwie zu reparieren. Eindeutiger könnte man die Frage des OP nicht beantworten.



  • Tim schrieb:

    Mit anderen Worten: Man nimmt was frickeliges als Basis und versucht das grundlegende Konzept irgendwie zu reparieren. Eindeutiger könnte man die Frage des OP nicht beantworten.

    Ich sehe keinen kausalen Zusammenhang, der die Sache am eindeutigsten machen würde. Soll heißen: schreibe die unumstößliche Beweiskette auf.



  • JustAnotherNoob schrieb:

    Du hättest deinen Spaß mit Python, die haben Datenkapselung durch Umbenennung der Member realisiert *huch* Trotzdem ist die Sprache objektorientiert 🙄

    mit dem Unterschied, daß Python eine betont lockere Sprache ist, die möglichst wenig verbieten und viel erlauben will - eine antiautoritäre Programmiersprache sozusagen 😃

    da paßt es doch nicht schlecht ins Konzept, wenn "private" oder "public" eine Sache freiwilliger Vereinbarung ist ...

    antiautoritär ist mein C++ Compiler hingegen aber ganz und gar nicht - einerseits meckert er jeden kleinen Typfehler bei mir an - andererseits compiliert er Objekte, deren Destruktor ich in einer while-Schleife beliebig oft hintereinadner ausführen könnte. Gute Pädagogik sieht anders aus 🙄 😃



  • volkard schrieb:

    Man hat sich nämlich Gedanken gemacht, wie man in C++ die bösesten Fallstricke von C entschärft.

    hätte man das wirklich getan, dann hätte man z.b. casts sehr eingeschränkt, array- und pointerzugriffe mit 'ner bereichsüberprüfung versehen, eingebauten datentypen feste längen spendiert, den void* abgeschafft, usw. aber nein, es musste ja mit aller gewalt C-kompatibel sein. *rolleyes*
    🙂



  • //fricky schrieb:

    hätte man das wirklich getan, dann hätte man z.b. casts sehr eingeschränkt, array- und pointerzugriffe mit 'ner bereichsüberprüfung versehen,

    Ist es nicht so, daß es überprüfende Container und Iteratoren schon lange gibt? Es muß gar kein Sprachmittel sein.

    eingebauten datentypen feste längen spendiert,

    Nimm doch <stdint.h> oder bau Dir was eigenes.
    Es muß gar kein Sprachmittel sein.

    den void* abgeschafft

    Wer benutzt in C++ denn void*?
    Das muß gar nicht weg, weil man void* praktisch nicht verwendet. Gerademal für eigene Implemetierungen von new/delete.

    , usw.

    Das lese icgh jetzt als
    "Nichts, usw."

    aber nein, es musste ja mit aller gewalt C-kompatibel sein. *rolleyes*
    🙂

    Ja, das Festhalten an der C-Syntax ist der Hauptgrund für die Kompliziertheit der Sprache. Aber wohl auch der Hauptgrund der starken Verbreitung.



  • was steht denn da? bestimmt sowas wie: mach das nicht, lass dieses, um himmels willen nein!, gefährlich, pass auf, usw...

    Das C++ eine Sammlung aus 4 Programmiersprachen ist: C, OOP-C++, Template-C++ und STL und man es als solche betrachten soll.
    Mir fällt immer wieder auf, dass du denkst, C++ würde sich wie C programmieren, wenn du es mit Java vergleichst, oder es würde sich wie Java programmieren, wenn du es mit C vergleichst, das ist Blödsinn.
    C++ hat High-Level _und_ Low-Level. Du musst niemals mit Low-Level Speicher arbeiten, du kannst deine Arrayindices btw. checken lassen, indem du vector nimmst und die at Methode verwendest, dann schmeißter ne Exception.

    aber nein, es musste ja mit aller gewalt C-kompatibel sein. *rolleyes*

    Man nehme Low-Level und Konzepte um aus Low-Level High-Level zu machen, das ist C++. Das ist der Grund für die Flexibilität von C++. Wenn du gleich High-Level nimmst sieht es syntaktisch schöner aus und ist einfacher, aber wesentlich unflexibler.

    antiautoritär ist mein C++ Compiler hingegen aber ganz und gar nicht - einerseits meckert er jeden kleinen Typfehler bei mir an - andererseits compiliert er Objekte, deren Destruktor ich in einer while-Schleife beliebig oft hintereinadner ausführen könnte. Gute Pädagogik sieht anders aus

    Was dein C++ Compiler ist tut nichts zur Sache, schreibe eine Warnung oder gar einen Fehler dafür, wenn es sich um den GCC handelt und submitte den. Wenn es nichts kostet werden sie es annehmen(kosten im Sinne von Performance). Der C++ Standard erlaubt das mehrfache ausführen von Destruktoren jedenfalls nicht. C++ an sich ist ähnlich wie das was du bei Python siehst, es wird nichts verboten, nur geschützt.



  • u_ser-l schrieb:

    antiautoritär ist mein C++ Compiler hingegen aber ganz und gar nicht - einerseits meckert er jeden kleinen Typfehler bei mir an - andererseits compiliert er Objekte, deren Destruktor ich in einer while-Schleife beliebig oft hintereinadner ausführen könnte.

    Das hat auch seine Richtigkeit. Schon mal von Turing gehört? Halteproblem und so?


Anmelden zum Antworten