Classes in C are most often modeled by structures combined with function pointers. Non-virtual functions can be passed along with a pointer to a structure, for example:
int obj_compare_funct(Obj *a, Obj *b); int result = compare_two_objects(obj1, obj2, obj_compare_func);
But the real fun begins when you insert pointers into a structure; this means that objects of the same โclassโ can have different โmethodsโ. The strongest syntax flaw is that the specified function does not automatically know for which object it is being called. Thus, the object must also be transferred, which allows you to type a little text than this is usually desirable. For instance:
typedef struct Animal { char *name; void (* speak)(Animal *this); } Animal; extern Animal *make_feline(char *name); extern Animal *make_rodent(char *name); Animal *cat = make_feline("Tom"); Animal *mouse = make_rodent("Jerry"); cat->speak(cat); mouse->speak(mouse);
This example is slightly weaker than the inheritance model provided by languages โโsuch as Java. An instance of Animal may have any behavior at all, and not one of a specific set of actions, depending on its subclass. To make things a little more rigorous, methods are usually combined into a structure called vtable (virtual function table). One virtual table is ready for each subtype, and the corresponding one points to an instance.
Note that none of this directly helps you to have different fields for each subtype - it is more complicated (especially syntactically) and can be done either by casting the object to its first member, for example:
typedef struct Cat { Animal super; int num_fleas; } Cat;
Or using opaque pointers like
typedef struct Animal { char *name; void *species_specific_data; } Animal;
If additional fields are hidden behind this void * pointer and are accessible through methods specific to this view.
source share