D   A   T   A   W   O   K





Creation: May 08 2016
Modified: September 18 2018

Inheritance in C

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

I assume that you are already familiar with object-oriented programming. Thus, for every subject, a very short theoretical introduction is given.


Inheritance enables new types to be defined extending existing types. Extending a type mainly means reusing a base type code to inherit behavious and implementation. The axiom that always holds with inheritance is that a derived type is a base type.

The C language does not explicitly support inheritance, but the developer can implement it by exploiting one simple language feature: the first member of the structure is always aligned to the structure start boundary. As a consequence, if we insert what is supposed to be the structure base class as the first member of the derived structure then:

The two properties above is effectivelly an implementation of inheritance, we can always use a derived type wherever a base type is expected.

Example

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)
{
    free(person->name);
    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)
{
    person_destruct(&student->super);
}

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 */
student_destruct(&stud);

Example sources download

davxy