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_destruct sum = 18, product = 210.
Critique request
I would like to hear comments on:
- naming conventions,
- coding conventions,
- overall comments,
- design pattern,
- anything else.