#include #include #include #include #include #define VIRTUAL #define PRIVATE struct _virtual_table { VIRTUAL void (*area)(void *self); VIRTUAL void (*draw)(void *self); }; void virtual_area(void *self) { assert(!"can't call abstract method"); } void virtual_draw(void *self) { assert(!"can't call abstract method"); } struct _virtual_table *virtual_new(void) { struct _virtual_table *v = calloc(1, sizeof(struct _virtual_table)); if (v == NULL) { return NULL; } v->area = virtual_area; v->draw = virtual_draw; return v; } struct _shape { VIRTUAL void (*area)(void *self); VIRTUAL void (*draw)(void *self); }; void shape_area(void *self) { assert(!"can't call abstract method"); } void shape_draw(void *self) { assert(!"can't call abstract method"); } struct _shape *shape_new(void) { struct _shape *shape = calloc(1, sizeof(struct _shape)); if(shape == NULL) { return NULL; } shape->area = shape_area; shape->draw = shape_draw; return shape; } #if 0 void shape_free(struct _shape * self) { if (self != NULL) { free(self); } } #endif #define SUPER(self) ((self)->shape) struct _rect { // super struct _shape* shape; // attribute double width, height; // method // void (*area)(void *self); // void (*draw)(void *self); }; void rect_area(struct _rect *self) { printf("rect area = %0.2f\n", self->width * self->height); } void rect_draw(struct _rect *self) { printf("rect draw\n"); } struct _rect *rect_new(double width, double height) { struct _rect *rect = calloc(1, sizeof(struct _rect)); if (rect == NULL) { return NULL; } rect->width = width; rect->height = height; rect->shape = shape_new(); if (rect->shape == NULL) { return NULL; } SUPER(rect)->area = (void (*)(void *self))rect_area; SUPER(rect)->draw = (void (*)(void *self))rect_draw; return rect; } struct _circle { // super struct _shape *shape; // attribute double radius; // method // void (*area)(void *self); // void (*draw)(void *self); }; void circle_area(struct _circle *self) { printf("circle area = %0.2f\n", 3.14 * self->radius * self->radius); } void circle_draw(struct _circle *self) { printf("circle draw\n"); } struct _circle *circle_new(double radius) { struct _circle *circle = calloc(1, sizeof(struct _circle)); if (circle == NULL) { return NULL; } circle->shape = shape_new(); if (circle->shape == NULL) { return NULL; } circle->radius = radius; SUPER(circle)->area = (void (*)(void *self))circle_area; SUPER(circle)->draw = (void (*)(void *self))circle_draw; return circle; } int main(int argc, char *argv[]) { struct _rect *rect = rect_new(4, 5); rect_area(rect); rect_draw(rect); struct _circle *circle = circle_new(3); circle_area(circle); circle_draw(circle); // struct shape *shape = shape_new(); // shape_area(shape); // shape_draw(shape); // struct _shape *shape = NULL; struct _shape *shape = rect_new(2,3); // shape = rect; shape_area(shape); shape_draw(shape); return 0; }