Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can Inheritance be modelled using C? [duplicate]

Tags:

c

oop

inheritance

Is it possible to model inheritance using C? How? Sample code will help.

Edit: I am looking to inherit both data and methods. Containership alone will not help. Substitutability - using any derived class object where a base class object works - is what I need.

like image 606
Agnel Kurian Avatar asked Aug 06 '09 06:08

Agnel Kurian


People also ask

How can we achieve inheritance in C programming?

In C, inheritance can be achieved by maintaining a reference to the base class object in the derived class object. With the help of the base class' instance, we can access the base data members and functions.

Is inheritance possible in C?

No it doesnt. C is not an Object Oriented language. Inheritance is a property of OO languages.

How does inheritance achieve code reuse?

Implementation inheritance is described as a way to achieve code reuse. This works by defining methods and variables in a class that is then inherited by other classes. Those other classes are said to be derived from the original class, and the original class is said to be their base class.

What is inheritance in C sharp with example?

In C#, inheritance allows us to create a new class from an existing class. It is a key feature of Object-Oriented Programming (OOP). The class from which a new class is created is known as the base class (parent or superclass). And, the new class is called derived class (child or subclass)


2 Answers

It is very simple to go like this:

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

But if you use MS extension (in GCC use -fms-extensions flag) you can use anonymous nested structs and it will look much better:

struct child {     struct parent;    // anonymous nested struct     int bar; };  struct child derived;  derived.bar = 1; derived.foo = 2;     // now it is flat 
like image 186
qrdl Avatar answered Sep 27 '22 23:09

qrdl


You can definitely write C in a (somewhat) object-oriented style.

Encapsulation can be done by keeping the definitions of your structures in the .c file rather than in the associated header. Then the outer world handles your objects by keeping pointers to them, and you provide functions accepting such pointers as the "methods" of your objects.

Polymorphism-like behavior can be obtained by using functions pointers, usually grouped within "operations structures", kind of like the "virtual method table" in your C++ objects (or whatever it's called). The ops structure can also include other things such as constants whose value is specific to a given "subclass". The "parent" structure can keep a reference to ops-specific data through a generic void* pointer. Of course the "subclass" could repeat the pattern for multiple levels of inheritance.

So, in the example below, struct printer is akin to an abstract class, which can be "derived" by filling out a pr_ops structure, and providing a constructor function wrapping pr_create(). Each subtype will have its own structure which will be "anchored" to the struct printer object through the data generic pointer. This is demontrated by the fileprinter subtype. One could imagine a GUI or socket-based printer, that would be manipulated regardless by the rest of the code as a struct printer * reference.

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); } 

Finally, 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); } 
like image 24
Jérémie Koenig Avatar answered Sep 27 '22 22:09

Jérémie Koenig