Hoe kan overerving worden gemodelleerd met C?

Is het mogelijk om overerving te modelleren met C? Hoe? Voorbeeldcode helpt.

Bewerken:ik wil zowel gegevens als methoden erven. Alleen containerschepen zullen niet helpen. Vervangbaarheid – elk afgeleid klasseobject gebruiken waar een basisklasseobject werkt – is wat ik nodig heb.


Antwoord 1, autoriteit 100%

Het is heel eenvoudig om als volgt te werk te gaan:

struct parent {
    int  foo;
    char *bar;
};
struct child {
    struct parent base;
    int bar;
};
struct child derived;
derived.bar = 1;
derived.base.foo = 2;

Maar als je de MS-extensie gebruikt (gebruik in GCC de vlag -fms-extensions), dan kun je anonieme geneste structs gebruiken en het ziet er veel beter uit:

struct child {
    struct parent;    // anonymous nested struct
    int bar;
};
struct child derived;
derived.bar = 1;
derived.foo = 2;     // now it is flat

Antwoord 2, autoriteit 46%

Je kunt C zeker in een (enigszins) objectgeoriënteerde stijl schrijven.

Inkapseling kan worden gedaan door de definities van uw structuren te behouden
in het .c-bestand in plaats van in de bijbehorende header.
Dan behandelt de buitenwereld je objecten door er verwijzingen naar te houden,
en je voorziet in functies die aanwijzingen accepteren zoals de “methoden”
van uw objecten.

Polymorfisme-achtig gedrag kan worden verkregen door functieaanwijzers te gebruiken,
meestal gegroepeerd in “operatiestructuren”,
een beetje zoals de “virtuele methodetabel” in je C++-objecten
(of hoe het ook heet).
De ops-structuur kan ook andere dingen bevatten, zoals:
constanten waarvan de waarde specifiek is voor een bepaalde “subklasse”.
De “ouder”-structuur kan een verwijzing naar ops-specifieke gegevens behouden
via een generieke void*aanwijzer.
Natuurlijk kan de “subklasse” het patroon voor meerdere niveaus herhalen
van erfenis.

Dus in het onderstaande voorbeeld is struct printerverwant aan een abstracte klasse,
die kan worden “afgeleid” door een pr_ops-structuur in te vullen,
en het verschaffen van een constructorfunctie die pr_create()omhult.
Elk subtype heeft zijn eigen structuur die wordt “verankerd”
naar het struct printer-object via de algemene aanwijzer data.
Dit wordt aangetoond door het subtype fileprinter.
Je zou je een GUI of socket-gebaseerde printer kunnen voorstellen,
die ongeacht de rest van de code zou worden gemanipuleerd
als struct printer *referentie.

printer.h:

struct pr_ops {
    void (*printline)(void *data, const char *line);
    void (*cleanup)(void *data);
};
struct printer *pr_create(const char *name, const struct output_ops *ops, void *data);
void pr_printline(struct printer *pr, const char *line);
void pr_delete(struct printer *pr);

printer.c:

#include "printer.h"
...
struct printer {
    char *name;
    struct pr_ops *ops;
    void *data;
}
/* constructor */
struct printer *pr_create(const char *name, const struct output_ops *ops, void *data)
{
    struct printer *p = malloc(sizeof *p);
    p->name = strdup(name);
    p->ops = ops;
    p->data = data;
}
void pr_printline(struct printer *p, const char *line)
{
    char *l = malloc(strlen(line) + strlen(p->name) + 3;
    sprintf(l, "%s: %s", p->name, line);
    p->ops->printline(p->data, l);
}
void pr_delete(struct printer *p)
{
    p->ops->cleanup(p->data);
    free(p);
}

Ten slotte, fileprinter.c:

struct fileprinter {
    FILE *f;
    int doflush;
};
static void filepr_printline(void *data, const char *line)
{
    struct fileprinter *fp = data;
    fprintf(fp->f, "%s\n", line);
    if(fp->doflush) fflush(fp->f);
}
struct printer *filepr_create(const char *name, FILE *f, int doflush)
{
    static const struct ops = {
        filepr_printline,
        free,
    };
    struct *fp = malloc(sizeof *fp);
    fp->f = f;
    fp->doflush = doflush;
    return pr_create(name, &ops, fp);
}

Antwoord 3, Autoriteit 12%

Ja, u kunt er herfunctie en C emuleren met behulp van de “type pining” -techniek. Dat is de verklaring van de basisklasse (struct) in de afgeleide klasse en gooide de afgeleide basis als basis:

struct base_class {
  int x;
};
struct derived_class {
  struct base_class base;
  int y;
}
struct derived_class2 {
  struct base_class base;
  int z;
}
void test() {
  struct derived_class d;
  struct derived_class2 d2;
  d.base.x = 10;
  d.y = 20;
  printf("x=%i, y=%i\n", d.base.x, d.y);
}

Maar u moet de basisklasse in de eerste positie in uw afgeleide structuur declareren, als u de afgeleide basis in een programma wilt uitgeven:

struct base *b1, *b2;
 b1 = (struct base *)d;
 b2 = (struct base *)d2;
 b1->x=10;
 b2->x=20;
 printf("b1 x=%i, b2 x=%i\n", b1->x, b2->x);

In dit snippel kunt u alleen de basisklasse gebruiken.

Ik gebruik deze techniek in mijn projecten: OOP4C


Antwoord 4, Autoriteit 5%

het zou in ieder geval tot op zekere hoogte mogelijk moeten zijn.

Wat heb je precies nodig om te modelleren? Het erfenis van de gegevens of de methoden?

bewerken : hier is een kort artikel dat ik heb gevonden: http: //Fluff.info/blog/arch/00000162.htm


Antwoord 5, Autoriteit 5%

Ik heb een objectsysteem in C gebruikt dat late-gebonden methoden heeft gebruikt, die voor object-oriëntatie met reflectie hebben toegestaan.

U kunt erover lezen hier .


Antwoord 6, Autoriteit 5%

#include <stdio.h> 
///////Class Cobj
typedef struct Cobj{
    int x;
    void (*setptr)(char * s,int val);
    int (*getptr)(char * s);
} Cobj;
void set(char * s,int val)
{
    Cobj * y=(Cobj *)s;
    y->x=val;
}
int get(char * s){
    Cobj * y=(Cobj *)s;
    return y->x;
}
///////Class Cobj
Cobj s={12,set,get};
Cobj x;
void main(void){
    x=s;
    x.setptr((char*)&x,5);
    s.setptr((char*)&s,8);
    printf("%d %d %d",x.getptr((char*)&x),s.getptr((char*)&s) ,sizeof(Cobj));
}

Antwoord 7, Autoriteit 2%

Deze link kan handig zijn – & GT; link

Basisvoorbeeld, is als volgt

struct BaseStruct
{
  // some variable
}
struct DerivedStruct
{
  struct BaseStruct lw;
  // some more variable
};

Other episodes