C zu C++ - Einfacherer Übergang?



  • veritySeeker schrieb:

    C++ ist C mit Klassen, wenn man von Feinheiten wie Function-Templates mal absieht.

    Genau, Feinheiten wie Templates, Exceptions, Namensräume, Funktions- und Operatorüberladung oder Referenzen, um ein paar zu nennen.

    Natürlich sind Klassen ein sehr wichtiges Feature von C++ – aber bei Weitem nicht das einzige, das zu C hinzugefügt wurde. Ohne die restlichen neuen Features schöpft man nur einen kleinen Teil des Potenzials von C++ aus. Bibliotheken wie wxWidgets, die nur sehr eingeschränktes C++ verwenden, ist gut anzusehen, wie sowas herauskommt.


  • Administrator

    veritySeeker schrieb:

    Viele C-Compiler kennen auch inline-Funktionen. Funktionen in C werden sogar automatisch "ge-inlined", wenn der Compiler dies für erforderlich hält. Außerdem sind Makros nichts schlechtes, wenn man mit ihnen umzugehen versteht. Jedes Teil einer Programmiersprache kann man korrekt gebrauchen oder mißbrauchen.

    Auch in C++ entscheidet der Kompiler ganz frei darüber, ob eine Funktion nun "ge-inlined" werden soll oder nicht. Und niemand sagt was gegen Makros, sie können gut eingesetzt werden und sind gerade in C oftmals sehr hilfreich. In C++ kann man aber auf verdammte viele Makros, welche in C verwendet werden, verzichten. Aber die C auf C++ Umsteiger machen dies meistens nicht und man sieht zum Beispiel Dinge wie:

    #define MY_CONSTANT 200
    // statt
    int const MY_CONSTANT = 200;
    
    #define MAX(a, b) ((a) > (b) ? (a) : (b))
    // statt
    template<typename T>
    T max(T const& lhs, T const& rhs)
    {
      return lhs > rhs ? lhs : rhs;
    }
    

    Das Problem von Makros ist ja, dass es nur eine dumme Textersetzung ist, welche sich überhaupt nicht bewusst ist, über den vorhanden Code. Zum Beispiel interessiert es die Makros überhaupt nicht, was ein Scope ist. Dadurch kann plötzlich riesen Unsinn passieren und man ist sich gar nicht bewusst wieso. Und in C++ definiert man auch nicht immer eindeutige Bezeichner im globalen Namensraum, sondern hat mehrere verschachtelte Namensräume, wodurch die einzelnen Bezeichner für Klassen und Funktionen meistens kurz sind. Und schon kommt es schnell mal zu Probleme mit den Makros. Typisches Beispiel ist dieser Fall:

    #include <windows.h> // WinAPI
    #include <limits>
    
    int main()
    {
      return std::numeric_limits<int>::max();
    }
    

    Kompiliert nicht wegen eines tollen C Makros.

    Eben weil die Makros so gefährlich sind, sollte man wenn möglich auf sie verzichten. Und in C++ hat man deutlich mehr Möglichkeiten, auf die Makros zu verzichten, also sollte man dies auch tun. Ein C Programmierer fällt aber schnell auf die C Vorgehensweise zurück, weil er daran gewöhnt ist. In C ist das auch absolut in Ordnung, in C++ hätte man aber bessere Möglichkeiten. Die bekannte Macht der Gewohnheit.

    veritySeeker schrieb:

    Ein C++ Programm ohne Klassen unterscheidet sich kaum von einem C-Programm.

    1. Wie willst du bei einem C++ Programm die Klassen wegnehmen und dann vergleichen? Bisschen unsinnige Aussage, nicht?
    2. C++ fügt nicht nur Klassen zu C dazu. Das ist eine etwas sehr eingeschränkte Sichtweise.
    3. Aber wahrscheinlich willst du sagen, dass man in C++ genau gleich programmiert wie in C einfach mit Klassen und diese Aussage ist definitiv falsch. Schau dir dazu einfach guter C++ und guter C Code an und du wirst sehen, wie sich die Dinge unterscheiden. Weil man eben andere Möglichkeiten hat, geht man die Dinge anders an. Man programmiert nicht prozeduralen Code und wirft den einfach in Klassen rein. Ein C und ein C++ Programm sind meistens völlig unterschiedlich aufgebaut und zwar wirklich grundlegend.

    Aber ... irgendwo hat diese Diskussion echt keinen Sinn. Die Unterschiede sind so offensichtlich, es gibt so viel Literatur dazu, welche dies wunderschön aufzeigt, es wurde schon so viel dazu geschrieben (nicht nur in diesem Thread) und es gibt immer noch welche, die es nicht sehen. Gut, wenn man es nicht sehen will, sieht man es nicht. Ich hoffe einfach, dass ihr nie C++ programmieren werdet, da dabei einfach nur scheuslicher, fehleranfälliger und unsauberer C++ Code entstehen wird. Programmiert also bitte weiterhin in C und kommt nicht auf die Idee C++ Code zu erstellen. Ich ärgere mich jedesmal, wenn ich eine schlecht programmierte "C mit Klassen" Bibliothek sehe.

    Grüssli



  • Nexus schrieb:

    veritySeeker schrieb:

    C++ ist C mit Klassen, wenn man von Feinheiten wie Function-Templates mal absieht.

    Genau, Feinheiten wie Templates, Exceptions, Namensräume, Funktions- und Operatorüberladung oder Referenzen, um ein paar zu nennen.

    Natürlich, aber Klassen (mit Konstruktoren und Destruktoren) sind das Entscheidende was C++ wirklich von C abhebt. C++ ohne Klassen wäre nichts wert.

    Dravere schrieb:

    #define MY_CONSTANT 200
    // statt
    int const MY_CONSTANT = 200;
    

    Const gibt es auch in C. Aber benutze enums für Konstanten. Ein "const" kann weggecastet werden. Enumerations sind wirklich konstant.



  • veritySeeker schrieb:

    Const gibt es auch in C. Aber benutze enums für Konstanten. Ein "const" kann weggecastet werden. Enumerations sind wirklich konstant.

    Wie kommt man nur auf so einen Unsinn?



  • volkard schrieb:

    veritySeeker schrieb:

    Const gibt es auch in C. Aber benutze enums für Konstanten. Ein "const" kann weggecastet werden. Enumerations sind wirklich konstant.

    Wie kommt man nur auf so einen Unsinn?

    Welche der vier Sätze hälst Du für Unsinn?


  • Administrator

    veritySeeker schrieb:

    C++ ohne Klassen wäre nichts wert.

    Java ohne Klassen wäre nichts wert.
    C# ohne Klassen wäre nichts wert.
    usw.
    Was ist dass denn für eine Aussagen? Können es auch auch so machen:
    C ohne Zeiger wäre nichts wert.

    Klar wenn du ein zentraler Bestandteil der Sprache wegnimmst, ist sie nicht mehr so viel wert! Aber deswegen zu sagen, dass der einzige Unterschied zwischen C und C++ nur die Klassen sind, ist eine ziemlich seltsame Schlussfolgerung, welche ich überhaupt nicht nachvollziehen kann. Sonst könnten wir ja auch sagen, dass der Unterschied zwischen Java, C#, usw. und C nur die Klassen sind, da Java, C#, usw. auch nichts wert sind ohne Klassen...

    Grüssli



  • veritySeeker schrieb:

    volkard schrieb:

    veritySeeker schrieb:

    Const gibt es auch in C. Aber benutze enums für Konstanten. Ein "const" kann weggecastet werden. Enumerations sind wirklich konstant.

    Wie kommt man nur auf so einen Unsinn?

    Welche der vier Sätze hälst Du für Unsinn?

    Alles von Dir ist Unsinn. Hier der Versuch, PI in einen enum zu stopfen. enum hat doch nicht den Zweck, const zu ersetzen. Wegcastbarkeit (mit undefiniertem Verhalten) ist auch kein Argument.



  • volkard schrieb:

    veritySeeker schrieb:

    volkard schrieb:

    veritySeeker schrieb:

    Const gibt es auch in C. Aber benutze enums für Konstanten. Ein "const" kann weggecastet werden. Enumerations sind wirklich konstant.

    Wie kommt man nur auf so einen Unsinn?

    Welche der vier Sätze hälst Du für Unsinn?

    Alles von Dir ist Unsinn. Hier der Versuch, PI in einen enum zu stopfen. enum hat doch nicht den Zweck, const zu ersetzen. Wegcastbarkeit (mit undefiniertem Verhalten) ist auch kein Argument.

    Zugegeben, Pi kann nicht per enum dargestellt werden. Hier hilft tatsächlich nur noch #define. Bevor jetzt jemand mit Typsicherheit kommt: #define M_PI 3.141592653589793238462643 hat einen Typ. Der Dezimalpunkt zeichnet die Konstante eindeutig als "double" aus.

    Wegcastbarkeit von "const" ist sehr wohl ein Argument (C++ unterstützt dies sogar noch durch den eigens dafür geschaffenen const_cast<...>). Ich ziehe es vor, wenn mir ein Compiler sagt, daß ich Mist baue, anstatt mich stillschweigend mit undefiniertem Verhalten zu bestrafen. Und ein #define ... Literal, oder enum, wirst Du mit allen Casts der Welt nicht beschreibbar machen können.

    Wie wir sehen, hat C++ gegenüber C in puncto Konstanten keine sinnvolle Neuerung gebracht, eher im Gegenteil: C++ hat, wie so oft, ein nichtvorhandenes Problem adressiert und damit eine zusätzliche Fehlermöglichkeit eingeführt, ohne auch nur das Geringste zu verbessern.



  • veritySeeker schrieb:

    Wegcastbarkeit von "const" ist sehr wohl ein Argument (C++ unterstützt dies sogar noch durch den eigens dafür geschaffenen const_cast<...>). Ich ziehe es vor, wenn mir ein Compiler sagt, daß ich Mist baue, anstatt mich stillschweigend mit undefiniertem Verhalten zu bestrafen.

    Absichtlich Mistbauen kann man immer.
    Aber du kannst ein const PI nicht verändern. Darum geht es doch. caste das const halt weg und weise zu - klappt eh nicht.

    Genauso ist das mit #define doof:

    #define PI 3
    
    int main() {
      cout<<PI;
    #undef PI
    #define PI 2
      cout<<PI;
    }
    

    auch nicht wirklich const. Oder enum?

    enum { PI=3; };
    int main() {
    #define PI 2;
      cout<<PI;
    }
    

    Das ist ein NULL Argument. Denn gegen boshaftigkeit kann man sich nicht schützen...


  • Administrator

    veritySeeker schrieb:

    Wegcastbarkeit von "const" ist sehr wohl ein Argument (C++ unterstützt dies sogar noch durch den eigens dafür geschaffenen const_cast<...>). Ich ziehe es vor, wenn mir ein Compiler sagt, daß ich Mist baue, anstatt mich stillschweigend mit undefiniertem Verhalten zu bestrafen. Und ein #define ... Literal, oder enum, wirst Du mit allen Casts der Welt nicht beschreibbar machen können.

    Wie wir sehen, hat C++ gegenüber C in puncto Konstanten keine sinnvolle Neuerung gebracht, eher im Gegenteil: C++ hat, wie so oft, ein nichtvorhandenes Problem adressiert und damit eine zusätzliche Fehlermöglichkeit eingeführt, ohne auch nur das Geringste zu verbessern.

    Wenn du schon die C++ Casts nennst, dann sollte dir klar sein, dass C++ durchaus sinnvolle Neuerungen gebracht hat, indem es einen separaten const_cast eingeführt hat.

    int const CONSTANT = 10;
    
    static_cast<int&>(CONSTANT) = 10; // FEHLER
    *reinterpret_cast<int*>(&CONSTANT) = 10; // FEHLER
    *((int*)&CONSTANT) = 10; // Tjaja, C halt.
    *const_cast<int*>(&CONSTANT) = 10; // Und nur so geht es mit C++ Casts. const_cast wird aber so gut wie nie verwendet.
    

    Wenn du also die C++ Casts verwendest, läufst du keine Gefahr eine Konstante zu beschreiben. Von wegen keine Neuerungen, eher keine Ahnung.

    Grüssli



  • Dravere schrieb:

    #define MY_CONSTANT 200
    // statt
    int const MY_CONSTANT = 200;
    

    Wer meint, dass es geschickter ist, Folgendes:

    #define MY_CONSTANT 200
    

    'kurzerhand und unter allen Umständen' durch
    [code|
    const int MY_CONSTANT = 200;
    [/code]
    zu ersetzen,

    ... der moege einmal versuchen, mittels ...

    int main(){
    float A[MY_CONSTANT] = {0.0f};
    /* ... */
    

    ein elementares statisches Array in seinem Programm zu verwenden.
    Der Compiler wird die Version, in der MY_CONSTANT als const int vereinbart wurde, nicht kompilieren (Mit dem Argument, dass der Ausdruck zwischen den Klammern konstant sein muss).
    Mit #define MY_CONSTANT hingegen schon.

    Wir lernen daraus: echte Konstanten (die auch aus der Sicht des Kompilers Konstanten sind!) erzeugt man mittels #define.
    const-Konstanten hingegen sind gar keine 'echten' Konstanten (zumindest nicht aus der Sicht des Compilers!).

    mfg



  • Der Compiler wird die Version, in der MY_CONSTANT als const int vereinbart wurde, nicht kompilieren.

    Dann hast du aber einen seltsamen Compiler. Meiner kompiliert das ohne Probleme.

    ...



  • SpanischesDorf1 schrieb:

    Dravere schrieb:

    #define MY_CONSTANT 200
    // statt
    int const MY_CONSTANT = 200;
    

    Wer meint, dass es geschickter ist, Folgendes:

    #define MY_CONSTANT 200
    

    'kurzerhand und unter allen Umständen' durch
    [code|
    const int MY_CONSTANT = 200;
    [/code]
    zu ersetzen,

    ... der moege einmal versuchen, mittels ...

    int main(){
    float A[MY_CONSTANT] = {0.0f};
    /* ... */
    

    ein elementares statisches Array in seinem Programm zu verwenden.
    Der Compiler wird die Version, in der MY_CONSTANT als const int vereinbart wurde, nicht kompilieren (Mit dem Argument, dass der Ausdruck zwischen den Klammern konstant sein muss).
    Mit #define MY_CONSTANT hingegen schon.

    Wir lernen daraus: echte Konstanten (die auch aus der Sicht des Kompilers Konstanten sind!) erzeugt man mittels #define.
    const-Konstanten hingegen sind gar keine 'echten' Konstanten (zumindest nicht aus der Sicht des Compilers!).

    mfg

    Wie war das nochmal, von C++ keine Ahnung aber trotzdem groß rumposaunen?

    #include <iostream>
    using namespace std;
    
    int main()
    {
      const int c = 20;
      char arr[c];
      cout << sizeof(arr);
    }
    

    Ausgabe:

    20
    

    Wie erwartet.



  • Nexus schrieb:

    Bibliotheken wie wxWidgets, die nur sehr eingeschränktes C++ verwenden, ist gut anzusehen, wie sowas herauskommt.

    Und wieso macht wxWidgets das? Und nicht nur wxWidgets; kaum eine größere Bibliothek macht Gebrauch von allen Möglichkeiten von C++. Natürlich kann man argumentieren, dass die Bibliotheken schon älter sind, aber wenn es stimmt, dass "C mit Klassen" so eine Krankheit ist und alles so viel besser wird, wenn man Exceptions bloß keine Macros und Zeiger usw. verwendet, sollte ja wohl nichts dagegen sprechen, das beim nächsten größeren Versionssprung zu ändern (AFAIK gab es solche Versuche bei wxWidgets und FLTK auch, die aber mehr oder weniger gescheitert sind).

    "C mit Klassen" ist einfach alles, was man wirklich braucht. Die Leute benutzen C++, weil sie Klassen brauchen und die in C etwas mühsam nachzubauen sind. Ein paar Sachen wie Templates sind vielleicht noch nützlich, wenn man vorsichtig ist, aber alles darüber hinaus ist eher was für Esoteriker und bringt nicht wirklich was, sondern sorgt nur für neue Probleme und macht alles unnötig kompliziert. C++ verdankt seine Popularität dem Hype zu einer Zeit, in der C++ wirklich weitestgehend als "C mit Klassen" betrachtet wurde. Es wäre für alle Beteiligten das beste gewesen, wenn C++ dabei belassen worden und so wie bei C nur ein paar Detailverbesserungen gemacht worden wären. Wenn Bjarne Stroustrup in den 80ern mit dem C++ so wie es heute ist angekommen wäre, hätten alle einen großen Bogen darum gemacht und lieber Objective C benutzt.



  • ... schrieb:

    Der Compiler wird die Version, in der MY_CONSTANT als const int vereinbart wurde, nicht kompilieren.

    Dann hast du aber einen seltsamen Compiler. Meiner kompiliert das ohne Probleme.

    Er wollte wohl auf den sog. 'Enum-Hack' hinweisen, der ja tatsächlich wohl häufig angewendet wird (oder wurde?) und C++ (bzw. die Compilerhersteller) auch wirklich nicht gut aussehen lässt.



  • namespace invader schrieb:

    [...]

    Wie wäre es, wenn Du einfach mal Fakten zu Deinen Aussagen aufführst? Du argumentierst ja nichteinmal richtig. Du schreibst einfach nur Deine persönliche Meinung hin. Hilfreich für den Fragensteller ist das ganz gewiss nicht.

    Die einzige Quelle die Du angeführt hast ist die zu "Defective C++". Eine Quelle die sich ausschließlich selbst referenziert. Was man von Quellen die sich selbst referenzieren zu halten hat, sollte jedem, der einmal eine wissenschaftliche Arbeit geschrieben hat, wohl klar sein.



  • namespace invader schrieb:

    Und wieso macht wxWidgets das? Und nicht nur wxWidgets;

    Weil sie zu alt sind um es besser zu wissen.

    "C mit Klassen" ist einfach alles, was man wirklich braucht. Die Leute benutzen C++, weil sie Klassen brauchen und die in C etwas mühsam nachzubauen sind.

    Schau dir Code von Heute an und von vor 15 Jahren.
    C++ hat sich weiterentwickelt, einige Entwickler dagegen nicht.
    channel9 bietet ab und zu einblick hinter die kulissen bei microsoft. da sieht man zB was sich so tut.

    leider sind viele entwickler auf dem niveau von 1998 geblieben. In C++ hat man in den letzten Jahren eben an der Sprache gebaut - das ist zB einer der Gründe warum die C++ Library so mager ist.

    Alleine deine Kritikpunkte sind doch ein super Beispiel warum C mit Klassen eben keine gute Idee ist. Denn deine Kritikpunkte gelten ja nur für C mit Klassen aber nicht für richtiges C++.

    Das ist diese doppel Moral die du nicht einsehen willst 😉



  • ... schrieb:

    Dann hast du aber einen seltsamen Compiler. Meiner kompiliert das ohne Probleme.

    Das hier kompiliert mein Compiler nicht:

    template<typename T> 
    T max(T const& lhs, T const& rhs) 
    { 
      return lhs > rhs ? lhs : rhs; 
    }
    
    int const MY_CONSTANT = max(10, 20); 
    
    int a[MY_CONSTANT];
    

    Ist er kaputt?



  • namespace invader schrieb:

    Ist er kaputt?

    geht mit enum ja auch nicht.
    wenn max kein konstanter ausdruck ist, kann die davon abhängige konstate nicht konstant sein.

    einfacht constexpr verwenden und gut ist. oder eben nicht max sondern einen konstanten ausdruck verwenden.

    willst du echt auf so ein niveau hinaus...?



  • Shade Of Mine schrieb:

    willst du echt auf so ein niveau hinaus...?

    Die Frage ist inzwischen ziemlich redundant. 😉


Anmelden zum Antworten