In the author's object system, each object struct contains as its first element a pointer to its class:
typedef struct Object1 {
Class *myclass;
int data;
} Object1;
typedef struct Object2 {
Class *myclass;
double data;
} Object2;
That means that by treating a void *
pointer to any object as a Class **
pointer, the class pointer can be followed without knowing the actual type of the object. This is allowed by the standard, because:
c11
6.7.2.1 Structure and union specifiers
15 [...] A pointer to a
structure object, suitably converted, points to its initial member (or if that member is a
bit-field, then to the unit in which it resides), and vice versa. [...]
So any pointer Object1 *
or Object2 *
etc. can be converted to a pointer to its first element i.e. Class **
(since the first element of either is of type Class *
, a pointer to the first element is of type Class **
). See In C, does a pointer to a structure always point to its first member? for more information.
This is a legal approach, but a little difficult to follow. An equivalent would be to write
typedef struct BaseObject {
Class *myclass;
} BaseObject;
and require that each object struct contain a BaseObject
instance as its first member; the delete
function would then cast self
to BaseObject *
and write ((BaseObject *) self)->myclass->dtor
:
void delete (void * self)
{
BaseObject *base = self;
if (self && base->myclass && base->myclass—>dtor)
self = base->myclass->dtor(self);
free(self);
}