Structure Inheritance in C

Can I inherit a structure in C? If so, how?

+49
c structure
Jul 11 '09 at 18:28
source share
12 answers

Closest you can get a pretty common idiom:

typedef struct { // base members } Base; typedef struct { Base base; // derived members } Derived; 

Since Derived starts with a copy of Base , you can do this:

 Base *b = (Base *)d; 

Where d is an instance of Derived . Thus, they are polymorphic. But having virtual methods is another task - for this you will need to have the equivalent of a vtable pointer in Base containing pointers to functions that take Base as their first argument (which you could call this ).

At what point can you use C ++!

+62
Jul 11 '09 at 18:34
source share

C does not have an explicit concept of inheritance, unlike C ++. However, you can reuse the structure in another structure:

 typedef struct { char name[NAMESIZE]; char sex; } Person; typedef struct { Person person; char job[JOBSIZE]; } Employee; typedef struct { Person person; char booktitle[TITLESIZE]; } LiteraryCharacter; 
+38
Jul 11 '09 at 18:34
source share

I like and used the idea of Type Inheritance in C.

For example:

 struct Animal { int weight; }; struct Felidae { union { struct Animal animal; } base; int furLength; }; struct Leopard { union { struct Animal animal; struct Felidae felidae; } base; int dotCounter; }; 

Using:

 struct Leopard leopard; leopard.base.animal.weight = 44; leopard.base.felidae.furLength = 2; leopard.dotCounter = 99; 
+33
Oct 05 2018-11-11T00:
source share

If your compiler supports anonymous structures, you can do this:

 typedef struct Base { // base members } Base_t; typedef struct { struct Base; //anonymous struct // derived members } Derived_t; 

Thus, elements of the base element can be captured directly, which is better.

+8
Aug 26 2018-12-12T00:
source share

If you want to use some gcc magic (which I assumed would work with the Microsoft C compiler), you can do something like:

 struct A { int member1; }; struct B { struct A; int member2; } 

With gcc, you can compile this with -fms-extensions (allows you to use unnamed structure elements, such as the Microsoft compiler). This is similar to the solution given by Daniel Erwicker, except that it allows you to access memeber1 to an instance of struct B. ie B.member1 instead of B.Amember1.

This is probably not the most portable approach and will not work if you use the C ++ compiler (semantics of semantics means that it updates / defines the structure of A instead of creating an instance).

If, however, you live on the land of gcc / C, this will work and do exactly what you want.

+7
May 13 '13 at 1:50 pm
source share

You can do the above

 typedef struct { // base members } Base; typedef struct { Base base; // derived members } Derived; 

But if you want to avoid casting pointers, you can use union pointers from Base and Derived .

+3
Jul 11 '09 at 19:05
source share

A slight deviation from the answer of anon (and the like). For one level of deep inheritance, you can do the following:

 #define BASEFIELDS \ char name[NAMESIZE]; \ char sex typedef struct { BASEFIELDS; } Person; typedef struct { BASEFIELDS; char job[JOBSIZE]; } Employee; typedef struct { BASEFIELDS; Employee *subordinate; } Manager; 

Thus, functions that accept a pointer to Person will accept a pointer to Employee or Manager (with casting), as in other answers, but in this case, initialization will also be natural:

 Employee e = { .name = "..."; ... }; 

against

 # as in anon answer Employee e = { .person.name = "..."; ... }; 

I suggest some popular projects do this (e.g. libuv)

UPDATE: there are also some good examples of a similar (but not the same) concept in implementing libsdl events using structures and joins.

+3
Feb 23 '16 at 22:58
source share

Compiling with -fms-extensions

Chart image

main.c

 #include "AbstractProduct.h" #include "Book.h" #include "Product.h" #include "TravelGuide.h" /***********************/ int main() { Product p = Product_new(); p.set_id(&p, 2); p.set_name(&p, "name2"); p.set_description(&p, "description2"); p.set_price(&p, 2000); p.display(&p); TravelGuide tg = TravelGuide_new(); tg.set_id(&tg, 1); tg.set_name(&tg, "name1"); tg.set_description(&tg, "description1"); tg.set_price(&tg, 1000); tg.set_isbn(&tg, "isbn1"); tg.set_author(&tg, "author1"); tg.set_title(&tg, "title1"); tg.set_country(&tg, "country1"); tg.display(&tg); } 

AbstractProduct.c

 #include "AbstractProduct.h" /*-------------------------------*/ static void set_id(AbstractProduct *this, int id) { this->id = id; } /*-------------------------------*/ static void set_name(AbstractProduct *this, char *name) { strcpy(this->name, name); } /*-------------------------------*/ static void set_description(AbstractProduct *this, char *description) { strcpy(this->description, description); } /*-------------------------------*/ static int get_id(AbstractProduct *this) { return this->id; } /*-------------------------------*/ static char *get_name(AbstractProduct *this) { return this->name; } /*-------------------------------*/ static char *get_description(AbstractProduct *this) { return this->description; } /*-------------------------------*/ static void display(AbstractProduct *this) { printf("-AbstractProduct- \n"); printf("id: %d\n", this->get_id(this)); printf("name: %s\n", this->get_name(this)); printf("description: %s\n", this->get_description(this)); printf("\n"); } /*-------------------------------*/ void AbstractProduct_init(AbstractProduct *obj) { obj->set_id = set_id; obj->set_name = set_name; obj->set_description = set_description; obj->get_id = get_id; obj->get_name = get_name; obj->get_description = get_description; obj->display = display; } /*-------------------------------*/ AbstractProduct AbstractProduct_new() { AbstractProduct aux; AbstractProduct_init(&aux); return aux; } 

AbstractProduct.h

 #ifndef AbstractProduct_H #define AbstractProduct_H #include <stdlib.h> #include <stdio.h> #include <string.h> /***********************/ typedef struct AbstractProduct{ int id; char name[1000]; char description[1000]; void (*set_id)(); void (*set_name)(); void (*set_description)(); int (*get_id)(); char *(*get_name)(); char *(*get_description)(); void (*display)(); } AbstractProduct; AbstractProduct AbstractProduct_new(); void AbstractProduct_init(AbstractProduct *obj); #endif 

Book.c

 #include "Book.h" /*-------------------------------*/ static void set_isbn(Book *this, char *isbn) { strcpy(this->isbn, isbn); } /*-------------------------------*/ static void set_author(Book *this, char *author) { strcpy(this->author, author); } /*-------------------------------*/ static void set_title(Book *this, char *title) { strcpy(this->title, title); } /*-------------------------------*/ static char *get_isbn(Book *this) { return this->isbn; } /*-------------------------------*/ static char *get_author(Book *this) { return this->author; } /*-------------------------------*/ static char *get_title(Book *this) { return this->title; } /*-------------------------------*/ static void display(Book *this) { Product p = Product_new(); p.display(this); printf("-Book- \n"); printf("isbn: %s\n", this->get_isbn(this)); printf("author: %s\n", this->get_author(this)); printf("title: %s\n", this->get_title(this)); printf("\n"); } /*-------------------------------*/ void Book_init(Book *obj) { Product_init((Product*)obj); obj->set_isbn = set_isbn; obj->set_author = set_author; obj->set_title = set_title; obj->get_isbn = get_isbn; obj->get_author = get_author; obj->get_title = get_title; obj->display = display; } /*-------------------------------*/ Book Book_new() { Book aux; Book_init(&aux); return aux; } 

Book.h

 #ifndef Book_H #define Book_H #include <stdlib.h> #include <stdio.h> #include <string.h> #include "Product.h" /***********************/ typedef struct Book{ Product; char isbn[1000]; char author[1000]; char title[1000]; void (*set_isbn)(); void (*set_author)(); void (*set_title)(); char *(*get_isbn)(); char *(*get_author)(); char *(*get_title)(); // void (*display)(); } Book; Book Book_new(); void Book_init(Book *obj); #endif 

Product.c

 #include "Product.h" /*-------------------------------*/ static void set_price(Product *this, double price) { this->price = price; } /*-------------------------------*/ static double get_price(Product *this) { return this->price; } /*-------------------------------*/ static void display(Product *this) { AbstractProduct p = AbstractProduct_new(); p.display(this); printf("-Product- \n"); printf("price: %f\n", this->get_price(this)); printf("\n"); } /*-------------------------------*/ void Product_init(Product *obj) { AbstractProduct_init((AbstractProduct*)obj); obj->set_price = set_price; obj->get_price = get_price; obj->display = display; } /*-------------------------------*/ Product Product_new() { Product aux; Product_init(&aux); return aux; } 

Product.h

 #ifndef Product_H #define Product_H #include <stdlib.h> #include <stdio.h> #include <string.h> #include "AbstractProduct.h" /***********************/ typedef struct Product{ AbstractProduct; double price; void (*set_price)(); double (*get_price)(); // void (*display)(); } Product; Product Product_new(); void Product_init(Product *obj); #endif 

TravelGuide.c

 #include "TravelGuide.h" /*-------------------------------*/ static void set_country(TravelGuide *this, char *country) { strcpy(this->country, country); } /*-------------------------------*/ static char *get_country(TravelGuide *this) { return this->country; } /*-------------------------------*/ static void display(TravelGuide *this) { Book b = Book_new(); b.display(this); printf("-TravelGuide- \n"); printf("country: %s\n", this->get_country(this)); printf("\n"); } /*-------------------------------*/ void TravelGuide_init(TravelGuide *obj) { Book_init((Book*)obj); obj->set_country = set_country; obj->get_country = get_country; obj->f = obj->display; obj->display = display; } /*-------------------------------*/ TravelGuide TravelGuide_new() { TravelGuide aux; TravelGuide_init(&aux); return aux; } 

TravelGuide.h

 #ifndef TravelGuide_H #define TravelGuide_H #include <stdlib.h> #include <stdio.h> #include <string.h> #include "Book.h" /***********************/ typedef struct TravelGuide{ Book; char country[1000]; void (*f)(); void (*set_country)(); char *(*get_country)(); // void *(*display)(); } TravelGuide; TravelGuide TravelGuide_new(); void TravelGuide_init(TravelGuide *obj); #endif 

Makefile

 .PHONY: clean define ANNOUNCE_BODY *********************************************** ************ start make ************** *********************************************** endef all: $(info $(ANNOUNCE_BODY)) clear; if [ -f binary/main ]; then rm binary/main; fi; # compiler gcc $(INC) -c -fms-extensions main.c -o binary/main.o gcc $(INC) -c -fms-extensions AbstractProduct.c -o binary/AbstractProduct.o gcc $(INC) -c -fms-extensions Product.c -o binary/Product.o gcc $(INC) -c -fms-extensions Book.c -o binary/Book.o gcc $(INC) -c -fms-extensions TravelGuide.c -o binary/TravelGuide.o # linker gcc binary/main.o \ binary/AbstractProduct.o \ binary/Product.o \ binary/Book.o \ binary/TravelGuide.o \ -o \ binary/main 
+2
Mar 13 '16 at 1:45
source share

C is not an object oriented language and therefore has no inheritance.

-2
Jul 11 '09 at 18:30
source share

You can imitate it, but you really cannot inherit.

-2
Jul 11 '09 at 18:30
source share

No, you can’t. imo the best approach to OOP in C is using ADT .

-3
Jul 11 '09 at 18:34
source share

No, you can’t. C does not support the concept of inheritance.

-four
Jul 11 '09 at 18:30
source share



All Articles