Please consider the following code.
enum type {CONS, ATOM, FUNC, LAMBDA};
typedef struct{
enum type type;
} object;
typedef struct {
enum type type;
object *car;
object *cdr;
} cons_object;
object *cons (object *first, object *second) {
cons_object *ptr = (cons_object *) malloc (sizeof (cons_object));
ptr->type = CONS;
ptr->car = first;
ptr->cdr = second;
return (object *) ptr;
}
In the cons function, variable ptr is of type cons_object*. But in the return value it is converted to type of object*.
- I am wondering how this is possible because
cons_objectandobjectare different structs. - Are there any issues in doing stuff like this?
Any thoughts!
This is fine and is a fairly common technique for implementing “object-orientation” in C. Because the memory layout of
structs is well-defined in C, as long as the two object share the same layout then you can safely cast pointers between them. That is, the offset of thetypemember is the same in theobjectstruct as it is in thecons_objectstruct.In this case, the
typemember tells the API whether theobjectis acons_objectorfoo_objector some other kind of object, so you might be see something like this:More commonly, I’ve seem implementations where the “parent” class is defined as the first member of the “child” class, like so:
This works in largely the same way, except you’ve got a strong gaurantee that the memory layout of the child “classes” will be the same as the parents. That is, if you add a member to the ‘base’
object, it’ll automatically be picked up by the children and you won’t have to manually make sure all of the structures are in sync.