Objektorientiert Programmieren in C


  • Mod

    Andromeda schrieb:

    Um welche Sprache es sich handelt, sage ich hier mal nicht, damit kein Flamewar ausbricht. 🙂

    Doch, sag an. Du meinst Java, oder? Und was meinst du, wie Java das macht? Weil Java jede Menge systemabhängigen Code enthält, den du dann in deinen Anwendungen aufrufst. Der systemabhängige Code ist da, du siehst ihn nur nicht. Das kannst du natürlich ebenso in C oder C++ machen und ist auch genau, was man normalerweise macht. Siehe z.B. OpenGL und seine Hilfswerkzeuge, mit denen man systemunabhängig anspruchsvollste Spiele entwickeln kann. Aber die eigentliche OpenGL-Implementierung ist natürlich hochgradig systemabhängig. Daher brauchst du für jedes System einen anderen Grafiktreiber (OpenGL) und eine andere JVM (Java).

    Denn, wie schon gesagt, Zauberei wurde noch nicht erfunden. Der Magier auf der Bühne hält bloß einen Vorhang vor die Sachen, die du nicht sehen sollst/brauchst.

    PS: Die JVMs sind übrigens gewiss nicht selber in Java geschrieben. Denk mal nach, warum.



  • SeppJ schrieb:

    Andromeda schrieb:

    Um welche Sprache es sich handelt, sage ich hier mal nicht, damit kein Flamewar ausbricht. 🙂

    Doch, sag an. Du meinst Java, oder? Und was meinst du, wie Java das macht? Weil Java jede Menge systemabhängigen Code enthält, den du dann in deinen Anwendungen aufrufst.

    Yepp, genau genommen liegt es nicht an der Sprache, sondern am Unterbau; an einer Laufzeitumgebung, die vieles wegabstrahiert und glattbügelt. Seit einiger Zeit geht man sogar noch einen Schritt weiter: https://de.wikipedia.org/wiki/Docker_(Software)

    Aber wie auch immer: C ist trotzdem geil. Es gibt wohl keine Sprache, die so alt und gleichzeitig so beliebt ist wie C. Die meisten anderen Sprachen steigen auf und verschwinden wieder in der Versenkung. Aber C nicht. C ist irgendwie unsterblich. C ist der absolute Evergreen unter den Programmiersprachen. 🙂



  • Andromeda schrieb:

    Aber wie auch immer: C ist trotzdem geil. Es gibt wohl keine Sprache, die so alt und gleichzeitig so beliebt ist wie C. Die meisten anderen Sprachen steigen auf und verschwinden wieder in der Versenkung. Aber C nicht. C ist irgendwie unsterblich. C ist der absolute Evergreen unter den Programmiersprachen. 🙂

    C ist schon okay, allerdings käme ich nicht auf die Idee die Sprache außerhalb von Erweiterungen für bereits vorhandene C-Projekte für irgendetwas komplett Neues zu verwenden. Der Hauptgrund dafür ist, dass man in C die Destruktoren manuell aufrufen muss - oder noch schlimmer und leider weit verbreitet: Man implementiert den Aufräumcode für verwendete Objekte werden in jeder Funktion neu. Nennt mich einen Chauvinisten, aber ich finde das unnötig unübersichtich und fehleranfällig (letzteres mag auch an meiner fehlenden C-Praxis liegen).

    Und übrigens @Dexter: Der Rant von Linus hat übrigens bei näherer Betrachtung sehr wenig Substanz, ich würde mich davon nicht zu sehr beeindrucken lassen. Der Text wird wohl nur wegen des Bekanntheit des Autors so oft zitiert. inhaltlich hat der nur unwesentlich mehr zu bieten als "Ich find C++ und besonders C++-Programmierer scheiße". Sowas sollte man nicht allzu ernst nehmen.



  • Finnegan schrieb:

    Und übrigens @Dexter: Der Rant von Linus hat übrigens bei näherer Betrachtung sehr wenig Substanz, ich würde mich davon nicht zu sehr beeindrucken lassen. Der Text wird wohl nur wegen des Bekanntheit des Autors so oft zitiert. inhaltlich hat der nur unwesentlich mehr zu bieten als "Ich find C++ und besonders C++-Programmierer scheiße". Sowas sollte man nicht allzu ernst nehmen.

    Doch, sollte man. Was jemand vom Format eines Linus erzählt, gerade auch in Hinsicht Programmierung, verdient besondere Beachtung.



  • Finnegan schrieb:

    Der Hauptgrund dafür ist, dass man in C die Destruktoren manuell aufrufen muss

    Und das ist ein Problem ... warum?

    Wir hatten die Diskussion schonmal. Am Ende kamen wir darauf, dass man am Liebsten einen nicht-redundanten, kritischen Aufräumpfad haben will, der über Labels am Ende der Funktion an beliebiger Stelle betreten werden kann und soll. Höhere Sprachen nehmen dem Programmierer die Verantwortung für das Erzeugen und Freigeben komplett weg, was für kleinere Projekte sinnvoll sein kann - aber für größere Projekte nur für mehr redundanten Code sorgt (ich rede hier nicht von verstecktem ctor- und dtor-Code, sondern von verschiedenen Codepfaden - ein Pfad benötigt eine bestimmtes, temporäres Objekt auf dem Stack, der andere nicht)..

    Im Grunde ist es ein Deppenschutz, ähnlich:

    if(KONSTANTE == variable)
    

    , nur um Sicherzustellen, dass der Gleichheitsoperator ja nie zur Zuweisung wird.

    Finnegan schrieb:

    oder noch schlimmer und leider weit verbreitet: Man implementiert den Aufräumcode für verwendete Objekte werden in jeder Funktion neu.

    Das ist natürlich komplett sinnlos. Aber genau deswegen macht man das ja objektorientiert - damit der Aufräumcode an einer Stelle steht und für ein Objekt gilt.



  • Andromeda schrieb:

    Doch, sollte man. Was jemand vom Format eines Linus erzählt, gerade auch in Hinsicht Programmierung, verdient besondere Beachtung.

    Beachtung findet es ja offensichtlich. Aber auch ein Linus kann Mist verzapfen. Und schon der erste Satz

    *YOU* are full of bullshit.

    diskreditiert den gesamten Beitrag und die Diskussion. Das ist ganz einfach ein Niveau auf dem ich mit niemanden anfange zu diskutierne. Egal ob der Linus Torvalds, ‎Bjarne Stroustrup oder wie auch immer heißt.

    Und, gute Leistungen heißt noch lange nicht, dass man jedes Word von denen für bare Münze nehmen sollte.



  • Schlangenmensch schrieb:

    Andromeda schrieb:

    Doch, sollte man. Was jemand vom Format eines Linus erzählt, gerade auch in Hinsicht Programmierung, verdient besondere Beachtung.

    Beachtung findet es ja offensichtlich. Aber auch ein Linus kann Mist verzapfen. Und schon der erste Satz

    *YOU* are full of bullshit.

    diskreditiert den gesamten Beitrag und die Diskussion.

    Das hätte auch von mir sein können.
    Linus ist eben auch nur ein Mensch. 😉



  • Nein, C ist nicht cool. Es ist ne ganz schlimme Seuche. U.a. deswegen weil es in C unvernünftig viel Aufwand ist bestimmte Dinge sauber zu machen, die eigentlich einfach sein sollten. Wie z.B. das ganze String-Handling. Was dazu führt dass Leute Abkürzungen nehmen und sich im Laufe der Zeit sogar gewisse fragwürdige Kompromisse (wie fixe Puffergrössen für quasi alles) als "das Mittel der Wahl" angewöhnen. Was zu viel schlechtem Code mit vielen Fehlern führt.

    Dummerweise gibt's für bestimmte Anwendungen keinen brauchbaren Ersatz. C++ wäre theoretisch für viele Dinge verwendbar, bloss sobald mal die Standard-Library verwenden möchte tritt man sich so viele Dependencies ein...



  • Schlangenmensch schrieb:

    Aber auch ein Linus kann Mist verzapfen. Und schon der erste Satz

    *YOU* are full of bullshit.

    diskreditiert den gesamten Beitrag und die Diskussion. Das ist ganz einfach ein Niveau auf dem ich mit niemanden anfange zu diskutierne.

    Naivling.
    Nur weil dir das Vokabular nicht passt, verschließt du dich seinen milliardenfach durch die Praxis bewiesenen Erkenntnissen.
    Torvalds hat es nicht nötig, mit irgendwem über C zu diskutieren.

    Schlangenmensch schrieb:

    Egal ob der Linus Torvalds, ‎Bjarne Stroustrup oder wie auch immer heißt.

    Torvalds ist ein Praktiker, der weiß also wovon er spricht und hat das milliardenfach durch die Praxis bewiesen.
    Stroustrup, Sutter und Co. sind Theoretiker, die wissen also nicht, wovon sie sprechen und haben auch diese ihre Unkenntnis durch die Nichtexistenz des Praxisbeweises nachgewiesen.

    Schlangenmensch schrieb:

    Und, gute Leistungen heißt noch lange nicht, dass man jedes Word von denen für bare Münze nehmen sollte.

    Torvalds ist der lebende Gott der C Praxis, ihm seine diesbezüglichen Aussagen nicht zu glauben, nur weil er sie nicht in diplomatische Worte fasst, ist naiv.

    Insofern gefällt mir die Bezeichnung "Anti-Visionär" für Torvalds ganz gut:
    https://www.nzz.ch/digital/25-jahre-linux-wie-die-pinguine-die-welt-eroberten-ld.111871



  • Die einzigen zwei Argumente, die er in der Email nennt, sind diese:

    - infinite amounts of pain when they don't work (and anybody who tells me
    that STL and especially Boost are stable and portable is just so full
    of BS that it's not even funny)

    - inefficient abstracted programming models where two years down the road
    you notice that some abstraction wasn't very efficient, but now all
    your code depends on all the nice object models around it, and you
    cannot fix it without rewriting your app.

    Der Rest ist eine Mischung aus 'C++ is Bullshit' und 'C is the only sane choice'.
    Nur mal so in den Raum gestellt


  • Mod

    dachschaden schrieb:

    Im Grunde ist es ein Deppenschutz, ähnlich:

    if(KONSTANTE == variable)
    

    Automatische Destruktoren sind kein Deppenschutz, sondern ein Sprachkonzept, welches dem Programmierer ganz neue Möglichkeiten gibt, die er in C nicht hat und auch mit egal wie viel Aufwand gar nicht haben kann. Wenn du wirklich so denkst, dann hat man dich für dumm verkauft.



  • SeppJ schrieb:

    Automatische Destruktoren sind kein Deppenschutz, sondern ein Sprachkonzept, welches dem Programmierer ganz neue Möglichkeiten gibt, die er in C nicht hat

    Zum Beispiel doppelten Code haben, oder noch mal eine Funktion zur Schnittstelle dazu, die sich um die eigentliche Allokation von Ressourcen kümmert? Danke, kenn ich schon. Bin ich nicht überzeugt von. Ich halte mir lieber das Recht vor, selbst bestimmen zu können, wann ich ein Objekt freigebe und wann nicht. Wenn es funktioniert, dann ist alles super. Wenn nicht, dann bin ich ein Depp. Mit beidem kann ich leben.



  • hustbaer schrieb:

    Nein, C ist nicht cool. Es ist ne ganz schlimme Seuche. U.a. deswegen weil es in C unvernünftig viel Aufwand ist bestimmte Dinge sauber zu machen, die eigentlich einfach sein sollten.

    C ist cool.
    C ist in der Hand von Könnern unschlagbar (siehe Torvalds).
    C ist keine schlimme Seuche. C ist in der Hand von Deppen eine Seuche.
    Nur ist es in C einfacher, Unsinn zu programmieren als z.B. in C++, wo einem ja bekanntlich "bestimmte Dinge" abgenommen werden. Und deswegen gehört C auch nicht in die Hände von Anfängern oder Professoren oder Buchautoren oder Theoretikern (die glauben, C "verbessern" zu müssen, damit auch der letzte Depp glaubt, er könne programmieren weil er unfallfrei ein paar Zeilen aneinanderreihen kann).
    Für wiederkehrende Anforderungen im Tagesgeschäft gibt es zuhauf Bibliotheken.
    Wenn sich nämlich Könner - die C durch und durch verstanden haben - die Aufgabe stellen, C an die Neuzeit anzupassen, dann kommt was anderes raus als C++:
    http://www.drdobbs.com/open-source/interview-with-ken-thompson/229502480



  • Wutz schrieb:

    Wenn sich nämlich Könner - die C durch und durch verstanden haben - die Aufgabe stellen, C an die Neuzeit anzupassen, dann kommt was anderes raus als C++

    Das nennt sich dann C90, C95, C99, C11 und Objective-C.



  • Haltet ihr das offizielle Werk "The C Programming Language" (Zweite Auflage) vom Entwickler der Sprache für eine gute Einstiegslektüre? Ich verfüge bereits über geringe Programmiererfahrungen, stehe also nicht auf dem Schlauch wenn er beispielsweise das Wort "Kontrollstrukturen" benutzt.



  • Hi nochmal. Ich habe zwar meine Präferenzen, aber dennoch nicht vor, mich an dem hier aufziehenden Flamewar zu beteiligen. Meine Einstellung zu C ist neutral,
    und mir ist bewusst dass vieles von meiner Arbeit mit C++ auf Problemlösungen basiert, die auf elegante Weise in C implementiert wurde.

    Ich möchte hier lediglich ein Beispiel dafür geben, weshalb mir die "manuellen Destruktoren" so wenig zusagen.
    Der folgende Code stammt aus dem GStreamer-Projekt, mit dem ich vor einiger Zeit zu tun hatte, da wir dafür für unser Projekt ein kleines Spezial-Plugin
    benötigten. Ich glaube die Codepassage hier ist ein gutes Beispiel dafür, wie objektorientierter C-Code in einem größeren Projekt aussieht. Es handelt
    sich hierbei nicht um ein Extrembeispiel, weder in die eine oder die andere Richtung. Ich habe die Funktion deshalb ausgesucht, weil sie meiner Meinung den
    durchschnittlichen Fall recht gut repräsentiert. Die Kommentare stammen von mir:

    static GstPad *
    gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad)
    {
      GstDecodeBin *dbin;
      GstPad *srcpad, *sinkpad;
      GstIterator *it = NULL;
      GValue item = { 0, };
    
      dbin = group->dbin;
    
      GST_LOG_OBJECT (dbin, "group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
    
      // Hilfsvariable indirekt notwendig weil Kontrollfluss vor "return" durch Aufräumcode laufen muss.
      srcpad = NULL; 
    
      if (G_UNLIKELY (!group->multiqueue))
        return NULL;
    
      if (!(sinkpad = gst_element_get_request_pad (group->multiqueue, "sink_%u"))) {
        GST_ERROR_OBJECT (dbin, "Couldn't get sinkpad from multiqueue");
        return NULL;
      }
    
      if ((gst_pad_link_full (pad, sinkpad,
                  GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)) {
        GST_ERROR_OBJECT (dbin, "Couldn't link demuxer and multiqueue");
        goto error; // DTOR-Call
      }
    
      it = gst_pad_iterate_internal_links (sinkpad);
    
      if (!it || (gst_iterator_next (it, &item)) != GST_ITERATOR_OK
          || ((srcpad = g_value_dup_object (&item)) == NULL)) {
        GST_ERROR_OBJECT (dbin,
            "Couldn't get srcpad from multiqueue for sinkpad %" GST_PTR_FORMAT,
            sinkpad);
        goto error; // DTOR-Call
      }
      CHAIN_MUTEX_LOCK (group->parent);
      group->reqpads = g_list_prepend (group->reqpads, gst_object_ref (sinkpad));
      CHAIN_MUTEX_UNLOCK (group->parent); // DTOR-Call
    
    // DTOR-Implementierung {
    beach: 
      if (G_IS_VALUE (&item))             
        g_value_unset (&item);
      if (it)
        gst_iterator_free (it);
      gst_object_unref (sinkpad);
    // }
      return srcpad;
    
    // DTOR-Implementierung {
    error:
      gst_element_release_request_pad (group->multiqueue, sinkpad);
      goto beach;
    // }
    }
    

    Das erste, was mir auffällt ist, dass 11 von 53 Zeilen dieser Funktion, also etwa 20% des Codes direkt oder indirekt dem Aufräum-Code zuzuordnen sind.
    Das ist nicht nur mehr Tipparbeit, sondern erschwert das Codeverständnis für außenstehende und hat mehr Zeilen in die man Fehler einbauen kann.

    Zweitens, auch wenn das hier noch ein sehr harmloses Beispiel ist, so vergleiche man z.B. Zeile 21 mit Zeile 27. Hier muss der Programmierer zusätzlichen
    Gehirnschmalz nur fürs Aufräumen investieren: Da in Zeile 27 der Referenzzähler für sinkpad anders als in Zeile 21 inkrementiert wurde ist hier statt eines
    simplen return NULL zusätzlicher Aufräumcode notwendig, der zentral in den error / beach -Blöcken behandelt wird. Wenn die Programmlogik etwas komplexer
    wird, kann man da schnell etwas übersehen, das eigentlich freigegeben werden müsste - ganz abgesehen davon dass in Zeile 27 noch nichts mit it und item
    gemacht wurde, der Aufräumcode aber dennoch in Zeilen 45 und 47 prüft, ob diese nicht vielleicht freigegeben werden müssen. Das ist nicht nur zusätzlich
    fehleranfällig, sondern eventuell auch noch ineffizient.

    Der dritte Punkt ist etwas weniger offensichtlich, aber etwas das ich bei der Arbeit mit solchen Bibliotheken immer als vermeidbaren Mehraufwand und zusätzliche
    Fehlerquelle empfand: Ob eine aufgerufene Funktion z.B. den Referenzzähler für ein Objekt selbständig erhöht und man selbst für das dekrementieren des
    selbigen zuständig ist, ob eine zurückgegebene Ressource selbst wieder freigegeben werden muss, oder ob eine Funktion, der man ein Objekt übergibt, den
    "Besitz" dieses Objekts übernimmt (Ressourcen müssen nicht selbst freigegeben werden oder Referenzzähler nicht dekrementiert werden), ist alleinig der
    Dokumentation zu entnehmen. So muss man während der Entwicklung sehr viel Aufwand und gewissenhafte Arbeit in die Struktur des eigenen Aufräumcodes
    stecken, wenn man korrekten Speicherleck- und double-free-freien Code schreiben will.

    Das sind alles Dinge, die mit automatischen Destruktoren nahezu komplett wegfallen, bzw. nur ein einziges Mal Arbeit machen. Das hat nichts mit Deppenschutz
    oder Unfähigkeit zu tun, sondern vor allem mit in meinen Augen verschwendeter Arbeitszeit, die ich persönlich lieber in die eigentlichen Algorithmen investiere.

    Gruss,
    Finnegan



  • Was ich noch nicht ganz verstehe: Mir wurde immer erklärt, dass C++ sozusagen die Erweiterung von C ist, insbesondere die Erweiterung um die Konzepte der Objektorientierung. Wenn man aber nun mit C objektorientiert programmieren kann, wozu brauche ich dann noch C++?

    Das soll keine Sprengstoff für Streitgespräche sein, sondern wirklich nur eine naive Frage eines Anfängers.

    Und meine Frage, ob ihr das Buch "The C Programming Language" von Ritchie und Kernighan für empfehlenswert haltet, möchte ich auch noch ebantwortet haben 😃 Habe in das Buch gerade reingeschnuppert, scheint in meinen Augen im Gegensatz zu den Kritiken anderer doch sehr einsteigerfreundlich zu sein.


  • Mod

    Dexter1997 schrieb:

    Was ich noch nicht ganz verstehe: Mir wurde immer erklärt, dass C++ sozusagen die Erweiterung von C ist, insbesondere die Erweiterung um die Konzepte der Objektorientierung. Wenn man aber nun mit C objektorientiert programmieren kann, wozu brauche ich dann noch C++?

    C++ bietet nativen Support für einige Konzepte, mit denen man objektorientiert Programmieren kann. In C muss man mit relativ viel Code das machen, was in C++ ein paar Zeichen sind. Technisch gesehen passiert aber in beiden Fällen das gleiche.

    Ansonsten solltest du C++ nicht so sehr als Erweiterung von C ansehen, sondern als eine ganz andere Sprache, die eine gemeinsame Wurzel mit C hat (bzw. deren Wurzel C ist). Wissen über C nützt dir in C++ herzlich wenig und umgekehrt. Außer du hast ganz viel Wissen über beide Sprachen, dann kannst du super erkennen, wie z.B. die ganze Objektorientierung in C++ "nur" Syntaxzucker ist, mit dem man kurz und einfach schreiben kann, was man sonst in C mit mehr Umständen machen würde.


Anmelden zum Antworten