This code snippet is a research attempt to find means for dealing with dynamic polymorphism (in C): two or more related classes share a common interface. Here is my best shot:#include <stdio.h>#include <stdlib.h>#define CALL(INTERFACE_PTR, METHOD_NAME, ...) \INTERFACE_PTR->METHOD_NAME(INTERFACE_PTR->object, ##__VA_ARGS__)#define DESTRUCT(INTERFACE_PTR) INTERFACE_PTR->destruct(INTERFACE_PTR->object)/******************************************************************************** Dummy data structures used for the demonstration.                            ********************************************************************************/typedef struct int_triple {    int a;    int b;    int c;} int_triple;typedef struct int_pointer_triple {    int* a;    int* b;    int* c;} int_pointer_triple;void int_triple_init(int_triple* it){    it->a = 0;    it->b = 0;    it->c = 0;}void int_pointer_triple_init(int_pointer_triple* ipt){    ipt->a = malloc(sizeof(int));    ipt->b = malloc(sizeof(int));    ipt->c = malloc(sizeof(int));    *ipt->a = 0;    *ipt->b = 0;    *ipt->c = 0;}void int_triple_set(void* int_triple_ptr, int a, int b, int c){    int_triple* it = (int_triple*) int_triple_ptr;    it->a = a;    it->b = b;    it->c = c;    printf(int_triple_set(%d, %d, %d)\n, a, b, c);}void int_pointer_triple_set(void* int_triple_pointer_ptr, int a, int b, int c){    int_pointer_triple* ipt = (int_pointer_triple*) int_triple_pointer_ptr;    *ipt->a = a;    *ipt->b = b;    *ipt->c = c;    printf(int_pointer_triple_set(%d, %d, %d)\n, a, b, c);}int int_triple_get_sum(void* int_triple_ptr){    int_triple* it = (int_triple*) int_triple_ptr;    puts(int_triple_get_sum());    return it->a + it->b + it->c;}int int_pointer_triple_get_sum(void* int_pointer_triple_ptr){    int_pointer_triple* ipt = (int_pointer_triple*) int_pointer_triple_ptr;    puts(int_pointer_triple_get_sum());    return *ipt->a + *ipt->b + *ipt->c;}int int_triple_get_product(void* int_triple_ptr){    int_triple* it = (int_triple*) int_triple_ptr;    puts(int_triple_get_product());    return it->a * it->b * it->c;}int int_pointer_triple_get_product(void* int_pointer_triple_ptr){    int_pointer_triple* ipt = (int_pointer_triple*) int_pointer_triple_ptr;    puts(int_pointer_triple_get_product());    return *ipt->a * *ipt->b * *ipt->c;}void int_triple_destruct(void* int_triple_ptr){    free(int_triple_ptr);    puts(int_triple_destruct());}void int_pointer_triple_destruct(void* int_pointer_triple_ptr){    int_pointer_triple* ipt = (int_pointer_triple*) int_pointer_triple_ptr;    free(ipt->a);    free(ipt->b);    free(ipt->c);    free(ipt);    puts(int_pointer_triple_destruct);}/******************************************************************************** Interface stuff.                                                             ********************************************************************************/typedef struct int_triple_interface {    void*  object;    void  (*set)         (void*, int, int, int);    int   (*get_sum)     (void*);    int   (*get_product) (void*);    void  (*destruct)    (void*);} int_triple_interface;int_triple_interface* new_int_triple(){    int_triple_interface* interface = malloc(sizeof(*interface));    int_triple* it = malloc(sizeof(*it));    int_triple_init(it);    interface->object      = it;    interface->set         = int_triple_set;    interface->get_sum     = int_triple_get_sum;    interface->get_product = int_triple_get_product;    interface->destruct    = int_triple_destruct;    return interface;}int_triple_interface* new_int_pointer_triple(){    int_triple_interface* interface = malloc(sizeof(*interface));    int_pointer_triple* ipt = malloc(sizeof(*ipt));    int_pointer_triple_init(ipt);    interface->object      = ipt;    interface->set         = int_pointer_triple_set;    interface->get_sum     = int_pointer_triple_get_sum;    interface->get_product = int_pointer_triple_get_product;    interface->destruct    = int_pointer_triple_destruct;    return interface;}int main() {    int_triple_interface* interface;    int sum;    int product;    puts(--- int_triple ---);    interface = new_int_triple();    CALL(interface, set, 2, 3, 4);    sum = CALL(interface, get_sum);    product = CALL(interface, get_product);    DESTRUCT(interface);    printf(sum = %d, product = %d.\n, sum, product);    puts(\n--- int_pointer_triple ---);    interface = new_int_pointer_triple();    CALL(interface, set, 5, 6, 7);    sum = CALL(interface, get_sum);    product = CALL(interface, get_product);    DESTRUCT(interface);    printf(sum = %d, product = %d.\n, sum, product);}The output from the main is as follows:--- int_triple ---int_triple_set(2, 3, 4)int_triple_get_sum()int_triple_get_product()int_triple_destruct()sum = 9, product = 24.--- int_pointer_triple ---int_pointer_triple_set(5, 6, 7)int_pointer_triple_get_sum()int_pointer_triple_get_product()int_pointer_triple_destructsum = 18, product = 210.Critique requestI would like to hear comments on:naming conventions,coding conventions,overall comments,design pattern,anything else.
Simulating dynamic polymorphism in C
c;polymorphism
Your approach has at least two unfortunate aspects:Your approach to interface->object uses an extra heap-allocation.Adding a new method to int_triple_interface requires increasing the size of every int triple object in the program by sizeof(void(*)()).Nit: Your DESTRUCT(x) macro doesn't actually free(x).The first problem could be solved by allocating the object data directly after the interface data, with allowances for alignment/padding:void int_triple_destruct(void* int_triple_ptr){    puts(int_triple_destruct() is now a no-op);}int_triple_interface* new_int_triple(){    int_triple_interface* interface = malloc(sizeof(*interface) + sizeof(int_triple));    int_triple* it = (void*)(interface + 1);    int_triple_init(it);    interface->object      = it;    interface->set         = int_triple_set;    interface->get_sum     = int_triple_get_sum;    interface->get_product = int_triple_get_product;    interface->destruct    = int_triple_destruct;    return interface;}The second problem could be solved by storing all your function pointers away in a static data table: one table per object type, instead of one table per object instance.#define CALL(INTERFACE_PTR, METHOD_NAME, ...) \INTERFACE_PTR->vtable->METHOD_NAME(INTERFACE_PTR->object, ##__VA_ARGS__)#define DESTRUCT(INTERFACE_PTR) INTERFACE_PTR->vtable->destruct(INTERFACE_PTR->object)typedef struct {    void  (*set)         (void*, int, int, int);    int   (*get_sum)     (void*);    int   (*get_product) (void*);    void  (*destruct)    (void*);} int_triple_vtable_t;int_triple_vtable_t int_triple_vtable = {    int_triple_set,    int_triple_get_sum,    int_triple_get_product,    int_triple_destruct,};typedef struct {    void* object;    int_triple_vtable_t* vtable;} int_triple_interface;int_triple_interface* new_int_triple(){    int_triple_interface* interface = malloc(sizeof(*interface) + sizeof(int_triple));    int_triple* it = (void*)(interface + 1);    int_triple_init(it);    interface->object = it;    interface->vtable = int_triple_vtable;    return interface;}You probably don't really need the object pointer at all (since now it just points to (char *)interface + k for some known offset k), but I haven't thought about it too much.In general, the question how do I do OOP in C can be answered by looking at what C++ does and then slavishly copying it. That's where I got the idea of vtables here, for example. Your object pointer is roughly equivalent to a C++ virtual base class. And if you really want to do efficient, type-safe OOP in C, you're eventually going to have to reckon with the concepts of copy construction and move construction, both of which you can find implemented in C++.