D   A   T   A   W   O   K

Creation: May 08 2016
Modified: January 28 2023

Inheritance in C

This article is part of a series that addresses the implementation of four of the most fundamental concepts of object-oriented programming using the standard C programming language:

It is assumed that you are already familiar with object-oriented programming. Thus, for each topic, only a brief theoretical introduction is provided.

Inheritance allows new types to be defined by extending existing types. Extending a type mainly means reusing the code of a base type to inherit its behavior and implementation. The principle that always holds with inheritance is that a derived type is a base type.

The C language does not explicit support inheritance, but developers can implement it by utilizing one simple language feature: the first member of the structure is always aligned to the beginning of the structure. As a result, if we include what is intended to be the base class structure as the first member of the derived structure then:

The two properties above effectivelly implement inheritance. That is, we can always use a derived type wherever a base type is expected.


Base class definition, a person

typedef struct person {
    char        *name;
} person_t;

Derived class definition, a student

typedef struct student {
    person_t    super;
    int         number;
} student_t;

Having defined the student_t in this way, every pointer to a student is also a pointer to its first member, a person. A student_t can be safely used wherever a pointer to a person_t is expected.

Base class constructor and destructor.

void person_construct(person_t *person, const char *name)
    person->name = malloc(strlen(name) + 1);
    strcpy(person->name, name);

void person_destruct(person_t *person)
    person->name = NULL;

Derived class constructor and destructor. Note the construction and destruction of the base class.

void student_construct(student_t *student, const char *name, int number)
    person_construct(&student->super, name);
    student->number = number;

void student_destruct(student_t *student)

Example of a person interface function

void person_print(person_t *person)
    printf("name: %s\n", person->name);

Usage example

student_t stud;
student_construct(&stud, "Davide", 123456);
person_print((person_t *) &stud);   /* explicit cast to prevent compiler warnings */

Example sources download

Proudly self-hosted on a cheap Raspberry Pi