Kapselung in C



  • Hallo zusammen,

    in C++ würde ich eine Klasse schreiben, um bestimmte Daten zu kapseln. In Java bin ich dazu sogar verpflichtet. Wie macht man dies in C? Ich kann mir nur schwer vorstellen, dass ich alle klassenlose Dateien schließlich rumfliegen habe und sie irgendwie verwende.

    Konkretes Beispiel: Ich habe den Horner - Algorithmus in C++ implementiert. Sobald ich diesen anwenden möchte, übergebe ich einer Methode die zu konvertierende Zahl als String. Diese gibt das Ergebnis gleich zurück. Mit Objektinitialisierung ergibt das zwei Zeilen.

    Wie wäre die Entsprechung in C?

    Vielen Dank
    LG, freakC++


  • Mod

    Im Prinzip genau so wie in C++, bloß von Hand:

    typedef struct
    {
      // Datenmember, z.B.
      int i;
    } meine_klasse;
    
    void meine_klasse_beispielmethode(meine_klasse *this, int parameter)
    {
      this->i = parameter;
    }
    
    // Gegebenenfalls noch Konstruktoren, Destruktoren, Zuweisungsoperator, usw.
    // Zum Beispiel Konstruktor und Destruktor:
    
    meine_klasse create_meine_klasse(int parameter)
    {
      meine_klasse val = {parameter};
      return val;
    }
    
    void destroy_meine_klasse(meine_klasse *this)
    {
      printf("Zerstöre meine_klasse mit i = %d\n", this->i);
    }
    
    // Dann Erstellung bei Bedarf und Zerstörung am Ende des Scopes:
    int main()
    {
      meine_klasse foo = create_meine_klasse(8);
      meine_klasse_beispielmethode(&foo, 9);
      destroy_meine_klasse(&foo);
    }
    

    Die Integrität der Datenkapselung liegt dabei in der Hand des Programmierers, dass er auf das Objekt nur über die Objektmethoden zugreift und die Finger von den Innereien lässt.



  • SeppJ schrieb:

    Die Integrität der Datenkapselung liegt dabei in der Hand des Programmierers, dass er auf das Objekt nur über die Objektmethoden zugreift und die Finger von den Innereien lässt.

    Hauptsache C bashen. Wer diese Kapselung zwingend braucht, hat sie auch in C.

    // meineklasse.h
    typedef struct MeineKlasse MeineKlasse; // der Nutzer kann nur MeineKlasse* verwenden
    
    MeineKlasse* create_meine_klasse(int parameter);
    void meine_klasse_beispielmethode(MeineKlasse *self, int parameter);
    void destroy_meine_klasse(MeineKlasse *self)
    
    //////////////////////////////
    // meineklasse.c
    
    struct MeineKlasse
    {
      // Datenmember, z.B.
      int i;
    };
    
    void meine_klasse_beispielmethode(MeineKlasse *self, int parameter)
    {
      self->i = parameter;
    }
    
    MeineKlasse* create_meine_klasse(int parameter)
    {
      MeineKlasse *self = malloc(sizeof*val);
      self->i = parameter;
      return val;
    }
    
    void destroy_meine_klasse(MeineKlasse *self)
    {
      printf("Zerstöre meine_klasse mit i = %d\n", this->i);
      free(self);
    }
    
    //////////////////////////////
    // main.c
    
    // Dann Erstellung bei Bedarf und Zerstörung am Ende des Scopes:
    int main()
    {
      meine_klasse foo = create_meine_klasse(8);
      meine_klasse_beispielmethode(&foo, 9);
      destroy_meine_klasse(&foo);
    }
    

    Konkretes Beispiel: Ich habe den Horner - Algorithmus in C++ implementiert. Sobald ich diesen anwenden möchte, übergebe ich einer Methode die zu konvertierende Zahl als String. Diese gibt das Ergebnis gleich zurück. Mit Objektinitialisierung ergibt das zwei Zeilen.

    Das funktioniert in C ganz genau gleich wie in Java.
    http://gmplib.org/manual/Initializing-Integers.html#Initializing-Integers



  • MeineKlasse* create_meine_klasse(int parameter) 
    { 
      MeineKlasse *self = malloc(sizeof*val); 
      self->i = parameter; 
      return val; 
    }
    

    ... return self; keine Ahnung, was sizeof*val ist. Weiterhin gibt wird self/this staendig inkonsitent benutzt.

    Ich wuerde in C einen opaquen Pointer bzw. Handle benutzen, bspw. void* .


  • Mod

    handlich schrieb:

    SeppJ schrieb:

    Die Integrität der Datenkapselung liegt dabei in der Hand des Programmierers, dass er auf das Objekt nur über die Objektmethoden zugreift und die Finger von den Innereien lässt.

    Hauptsache C bashen. Wer diese Kapselung zwingend braucht, hat sie auch in C.

    Gar nichts bashen, sondern Nennung der Fakten. Du hast den von mir gemachten Punkt nicht verstanden: Die Selbstzurückhaltung von der du sprichst ist genauso nötig in C++ (und Java wahrscheinlich auch, ich kenne die Sprache nicht gut genug). Der Programmierer könnte nämlich die Kapselung leicht aushebeln, wenn er wollte. Der wichtige Unterschied ist, dass er sie in C++ nicht versehentlich umgehen kann. Dies ist die in C nötige Selbstdisziplin: Man muss immer selber daran denken, das Objekt richtig zu erstellen, zu benutzen und zu zerstören. Wenn man es vergisst, dann hat man einen Laufzeitfehler. Wenn man es in C++ nicht richtig macht, dann meckert der Compiler. Und es ist in C++ wesentlich schwieriger, es nicht richtig zu machen, denn "richtig" bedeutet meistens, gar nichts zu tun (automatischer Destruktor).

    Dein Pimpl ändert gar nichts an dieser Problematik. Die ist in der Sprache eingebaut. Oder nein, das ist doof formuliert, denn es ist kein eingebautes Problem der Sprache. Besser: In C++ ist als Feature eingebaut, dass diese Selbstdisziplin nicht nötig ist.

    Kapselung ist nicht dazu da, Daten vor dem Programmierer zu schützen, sondern den Programmierer vor sich selbst!



  • Warum will man in C etwas machen (hier Kapselung), was eigentlich nicht vorgesehen ist und wofür deutlich besser z.B. C++ geeignet ist? 😕
    Ich verstehe das Ziel dieser Frage nicht!


  • Mod

    Vermutlich muss er einfach in C machen. Und dann ist das eine recht gute Methode der Programmierung. Man kann in jeder Sprache objektorientiert arbeiten. Alle großen Bibliotheken sind nach diesem Prinzip aufgebaut, in Teilen sogar die Standardbibliothek (File-IO).



  • SeppJ schrieb:

    Man kann in jeder Sprache objektorientiert arbeiten.

    Was ist an diesem Beispiel objektorientiert?


  • Mod

    764236 schrieb:

    SeppJ schrieb:

    Man kann in jeder Sprache objektorientiert arbeiten.

    Was ist an diesem Beispiel objektorientiert?

    Alles?

    Alan Kay schrieb:

    1. Everything is an object, 2. Objects communicate by sending and receiving messages (in terms of objects), 3. Objects have their own memory (in terms of objects), 4. Every object is an instance of a class (which must be an object), 5. The class holds the shared behavior for its instances (in the form of objects in a program list), 6. To eval a program list, control is passed to the first object and the remainder is treated as its message

    1. check
    2. check
    3. check
    4. check
    5. check
    6. hier im Beispiel noch nicht, könnte man aber.

    Oder

    ISO/IEC 2382-15- schrieb:

    Pertaining to a technique or a programming language that supports objects, classes, and inheritance

    objects: check
    classes: check
    inheritance: hier im Beispiel noch nicht, könnte man aber.

    Oder

    Wikipedia schrieb:

    Object-oriented programming (OOP) is a programming paradigm that represents concepts as "objects" that have data fields (attributes that describe the object) and associated procedures known as methods. Objects, which are usually instances of classes, are used to interact with one another to design applications and computer programs.

    objekcts: check
    data fields: check
    methods: check
    classes: check
    interaction: check

    Was fehlt dir?



  • handlich schrieb:

    int main()
    {
      meine_klasse foo = create_meine_klasse(8); /* falsch: foo muss Zeiger sein */
      meine_klasse_beispielmethode(&foo, 9);     /* demzufolge hier ohne & */
      destroy_meine_klasse(&foo);                /* demzufolge hier ohne & */
    }
    

    Natürlich geht OOP auch in purem C. 👍
    Zumindestens die allgemein anerkannten Grundlagen und nicht irgendwelche Sprachfeatures irgendwelcher Möchtegern-OOP-Sprachen, die gern mit OOP gleichgesetzt werden bzw. deren Einsatz viele Leute glauben lässt, sie beherrschten OOP.


Anmelden zum Antworten