Wie wird in C gekapselt?



  • Hallo liebe C-Gemeinde,

    ich lerne zwar C++ aber mich würde mal interessieren wie ihr denn in C eure Daten und Funktionen dazu kapselt? Macht ihr das nur über Namenpre- oder postfixe oder wie haltet ihr die vielen Funktionen auseinander, ich glaube es gibt ja nicht mal Namensräume oder?



  • Richtig, es gibt keine Namensräume. Das letzte mal, als ich wirklich reines C programmiert habe, habe ich mit Präfixen arbeiten müssen; dabei habe ich allerdings eine Art OOP genutzt, bei dem die Funktionen als Zeiger in structs zur Verfügung gestellt wurden...



  • /rant/ schrieb:

    dabei habe ich allerdings eine Art OOP genutzt, bei dem die Funktionen als Zeiger in structs zur Verfügung gestellt wurden...

    Das hat mit OOP eigentlich nichts zu tun. Das ist nur Resourcen verschwendet. Es ist lediglich Syntax-Zucker, denn ob man nun...

    object.method(par);
    

    oder...

    method(object, par);
    

    schreibt...



  • Wenn ich mit C Libs arbeite bspw. die GNOME-Libraries, sind diese öfters so aufgebaut:

    struct privObjekt // Darf nur intern von der Library benutzt werden.
    {
       // Attribute
    };
    
    struct Objekt // Darf nur vom Kunden angewendet werden. 
    {
       privObjekt priv; // Darf nur von der Library intern benutzt werden.
       // Attribute die der Kunde benutzen darf.
       int x;
       int y;
       double width;
       double height;
    };
    

    Und in der Dokumentation wird nur dieser Teil erwähnt und erklärt:

    struct Objekt
    {
        int x;
        int y;
        double width;
        double height;
    };
    

    Die Library zeigt nicht, dass 'Objekt' eine weitere Struktur in sich hat. Sie erwähnt nur, dass man die Struktur 'privObjekt' nicht nutzen sollte.

    Meintest du sowas?



  • Überlicherweise geschieht eine Kaspelung durch Auslagerung in einzelne C-Module, wo dann über den Speicherklassen-Spezifizierer "static" gesteuert wird, was an Daten/Funktionen nach außen sichtbar ist oder nicht. Zum Einsatz für den dynamischen Zugriff kommen dann u.a. auch Callbacks.



  • Tim schrieb:

    /rant/ schrieb:

    dabei habe ich allerdings eine Art OOP genutzt, bei dem die Funktionen als Zeiger in structs zur Verfügung gestellt wurden...

    Das hat mit OOP eigentlich nichts zu tun. Das ist nur Resourcen verschwendet. Es ist lediglich Syntax-Zucker, denn ob man nun...

    object.method(par);
    

    oder...

    method(object, par);
    

    schreibt...

    Der Sinn von Funktionszeigern in structs ist auch nicht das man object.method() schreiben kann (müsste in C eh object.method (object) sein), sondern dass man eben die Methoden aufruft, die das Objekt zur Verfügung stellt.
    Das ist schon ein wichtiger Aspekt von OOP.



  • meine Meinung nach ist das immer noch Syntax-Zucker. Ich mache immer so:

    typedef struct objA {
     ...
    } objA;
    
    objA *objA_create(void);
    void objA_free(objA *obj);
    int objA_set_xyz(objA *obj, ...);
    int objA_do_this(objA *obj);
    int objA_do_that(objA *obj);
    ...
    
    typedef struct objB {
     ...
    } objB;
    
    objB *objB_create(void);
    void objB_free(objB *obj);
    int objB_set_xyz(objB *obj, ...);
    int objB_do_this(objB *obj);
    int objB_do_that(objB *obj);
    

    da ist auch ganz klar, dass objB_do_that() nur für objB-Objekte gültig ist und vom objB angeboten wird.



  • supertux schrieb:

    meine Meinung nach ist das immer noch Syntax-Zucker.

    was? funktionszeiger in structs?



  • genau



  • dann hast du auch nicht verstanden wieso da funktionszeiger drin sind. Das hat nichts mit Syntax-Zucker zu tun.

    Hier mal ein Beispiel-Ausschnitt wie ich mich in C an OOP versucht habe:

    struct sexp_type_info {
        const char* name;
        void (*free) (struct sexp*);
        bool (*eq) (struct sexp*, struct sexp*);
        void (*write) (struct sexp*, void (*f) (const char*, void*), void* fx);
        void (*string_rep) (struct sexp*, char* dest, size_t max);
        struct sexp* (*copy) (struct sexp*);
    };
    
    struct sexp { // Basisklasse
        struct sexp_type_info* type_info;
    };
    
    struct sexp_number_t { // Abgleitet1
        struct sexp exp;
        int number;
    };
    
    struct sexp_pair_t { // Abgleitet2
        struct sexp exp;
        struct sexp* first;
        struct sexp* rest;
    };
    
    void
    sexp_free (struct sexp* e) {  // EDIT: diese funktion ist Syntax-Zucker
        if (e)
            e->type_info->free (e);
    }
    
    void
    pair_type_free (struct sexp* e) {
        if (e) {
            sexp_free (SEXP_FIRST (e));
            sexp_free (SEXP_REST (e));
            free (e);
        }
    }
    
    struct sexp*
    sexp_pair (struct sexp* first, struct sexp* rest) {
        static struct sexp_type_info type_info_pair = {
            "PAIR",
            pair_type_free,
            pair_type_eq,
            pair_type_write,
            pair_type_string_rep,
            pair_type_copy,
        };
    
        struct sexp_pair_t* n = malloc (sizeof (*n));
        if (!n)
            return error (err_out_of_memory);
        n->exp.type_info = &type_info_pair;
        n->first = first;
        n->rest = rest;
        return SEXP (n);
    }
    


  • igitt rtti 👎



  • C kannte nur die Kapselung von Daten (Zuständigkeitsbereiche), nicht die von Funktionen. Funktionsüberlagerungen nach Typen oder Parametern wurden erst mit C++ eingeführt zusammen mit OOP. Danke an die Entwickler von C++!

    Besser gleich C++ einsetzen als selbstgestricktes IGITT in C. Selbst wenn es läuft, ist es wenig übersichtlich! 😃



  • äh ja, am besten gleich C++ einsetzen und C abschaffen

    aber ansonsten ist das so erstmal kein "IGITT", sondern gängige Praxis.



  • äh ja, am besten gleich C++ einsetzen und C abschaffen

    👍



  • Oder C für das einsetzen wofür es auch geschaffen wurde. Ist doch klar, dass OOP in C schrecklich aussieht. Deswegen sollte man in C auch nicht Objektorientiert programmieren. Das scheint ihr zu vergessen.



  • So ein Blödsinn.



  • Meinst du meinen Beitrag. Warum sollte der Blödsinn sein? Argumente?



  • Ja deinen Beitrag. Was soll denn das sein, "wofür C geschaffen wurde"? Hello-World-Programme die nicht über 1000 Zeilen groß werden?

    Im übrigen sieht das auch nicht schrecklich aus.



  • C ist für Funktionale Programmierung geschaffen worden.
    Und dementsprechend sollte man es auch benutzen. Da in diesem Forum immer wieder gerne Analogien benutzt werden, werde ich dies auch mal tun: Ich beschwere mich ja auch nicht darüber, dass ich mit meinem Toaster nicht gut Kuchen backen kann.



  • player424 schrieb:

    C ist für Funktionale Programmierung geschaffen worden.

    ja nee is klar 😃

    btw: Es gibt auch Pizza und Schnitzel für den Toaster. Da sollte Kuchen doch auch gehen. Aber da passt die Analogie noch weniger.


Anmelden zum Antworten