> cat Point.h #ifndef GUARD_Point_h #define GUARD_Point_h 1 typedef struct Point { // representation double X; double Y; } Point; // functions double Point_x(const Point* p); double Point_y(const Point* p); Point* Point_initialize(Point* p, double x, double y); // constructors Point Point_createExplicit(double x, double y); Point Point_createDefault(void); Point* Point_newExplicit(double x, double y); Point* Point_newDefault(void); // destructors void Point_destroy(const Point* p); void Point_delete(const Point* p); #endif // GUARD_Point_h > cat Point.c // gcc -Wall -std=c99 -pedantic -I. -O2 -c Point.c #include #include // functions double Point_x(const Point* p) { return p->X; } double Point_y(const Point* p) { return p->Y; } Point* Point_initialize(Point* p, double x, double y) { p->X = x; p->Y = y; return p; } // constructors Point Point_createExplicit(double x, double y) { Point p; Point_initialize(&p, x, y); return p; } Point Point_createDefault(void) { return Point_createExplicit(0.0, 0.0); } Point* Point_newExplicit(double x, double y) { Point* p = (Point*)malloc(sizeof(Point)); Point_initialize(p, x, y); return p; } Point* Point_newDefault(void) { return Point_newExplicit(0.0, 0.0); } // destructors void Point_destroy(const Point* p) { } void Point_delete(const Point* p) { Point_destroy(p); free((void*)p); } > cat Color.h #ifndef GUARD_Color_h #define GUARD_Color_h 1 typedef struct Color { // representation unsigned int R; // red unsigned int G; // green unsigned int B; // blue } Color; // functions unsigned int Color_red(const Color *c); unsigned int Color_green(const Color *c); unsigned int Color_blue(const Color *c); Color* Color_initialize(Color* c, unsigned int r, unsigned int g, unsigned int b); // constructors Color Color_createExplicit( unsigned int r, unsigned int g, unsigned int b); Color Color_createDefault(void); Color* Color_newExplicit( unsigned int r, unsigned int g, unsigned int b); Color* Color_newDefault(void); // destructor void Color_destroy(const Color *c); void Color_delete(const Color *c); #endif // GUARD_Color_h > cat Color.c // gcc -Wall -std=c99 -pedantic -I. -O2 -c Color.c #include #include // functions unsigned int Color_red(const Color *c) { return c->R; } unsigned int Color_green(const Color *c) { return c->G; } unsigned int Color_blue(const Color *c) { return c->B; } Color* Color_initialize(Color* c, unsigned int r, unsigned int g, unsigned int b) { c->R = r; c->G = g; c->B = b; return c; } // constructors Color Color_createExplicit( unsigned int r, unsigned int g, unsigned int b) { Color c; Color_initialize(&c, r, g, b); return c; } Color Color_createDefault(void) { return Color_createExplicit(0, 0, 0); } Color* Color_newExplicit( unsigned int r, unsigned int g, unsigned int b) { Color* c = (Color*)malloc(sizeof(Color)); Color_initialize(c, r, g, b); return c; } Color* Color_newDefault(void) { return Color_newExplicit(0, 0, 0); } // destructors void Color_destroy(const Color *c) { } void Color_delete(const Color *c) { Color_destroy(c); free((void*)c); } > cat Shape.h #ifndef GUARD_Shape_h #define GUARD_Shape_h 1 #include #include typedef struct Shape { // representation const void* V; // virtual function table pointer Point P; Color C; } Shape; // functions const Point* Shape_point(const Shape* s); const Color* Shape_color(const Shape* s); void actualShape_draw(const Shape* s); double actualShape_area(const Shape* s); void Shape_draw(const Shape* s); // virtual function double Shape_area(const Shape* s); // virtual function Shape* Shape_initialize(Shape* s, const void* v, const Point* p, const Color* c); // constructors Shape Shape_createExplicit( const Point* p, const Color* c); Shape Shape_createDefault(void); Shape* Shape_newExplicit( const Point* p, const Color* c); Shape* Shape_newDefault(void); // destructors void Shape_destroy(const Shape* s); void Shape_delete(const Shape* s); #endif // GUARD_Shape_h > cat Shape.c // gcc -Wall -std=c99 -pedantic -I. -O2 -c Shape.c #include #include #include // functions const Point* Shape_point(const Shape* s) { return &(s->P); } const Color* Shape_color(const Shape* s) { return &(s->C); } void actualShape_draw(const Shape* s) { fprintf(stderr, "Shape_draw(const Shape*)\n"); fflush(stderr); } double actualShape_area(const Shape* s) { fprintf(stderr, "Shape_area(const Shape*)\n"); fflush(stderr); return 0.0; } typedef struct Shape_vtable_t { void (*Shape_draw)(const Shape*); double (*Shape_area)(const Shape*); } Shape_vtable_t; static const Shape_vtable_t Shape_vtable = {actualShape_draw, actualShape_area}; void Shape_draw(const Shape* s) { // virtual function ((Shape_vtable_t*)(s->V))->Shape_draw(s); } double Shape_area(const Shape* s) { // virtual function return ((Shape_vtable_t*)(s->V))->Shape_area(s); } Shape* Shape_initialize(Shape* s, const void* v, const Point* p, const Color* c) { s->V = v; Point_initialize(&(s->P), Point_x(p), Point_y(p)); Color_initialize(&(s->C), Color_red(c), Color_green(c), Color_blue(c)); return s; } // constructors Shape Shape_createExplicitShape( const Point* p, const Color* c) { Shape s; Shape_initialize(&s, (const void*)(&Shape_vtable), p, c); return s; } Shape Shape_createDefault(void) { Shape s; Point p = Point_createDefault(); Color c = Color_createDefault(); Shape_initialize(&s, (const void*)(&Shape_vtable), &p, &c); Color_destroy(&c); Point_destroy(&p); return s; } Shape* Shape_newExplicitShape( const Point* p, const Color* c) { Shape* s = (Shape*)malloc(sizeof(Shape)); Shape_initialize(s, (const void*)(&Shape_vtable), p, c); return s; } Shape* Shape_newDefault(void) { Shape* s = (Shape*)malloc(sizeof(Shape)); Point p = Point_createDefault(); Color c = Color_createDefault(); Shape_initialize(s, (const void*)(&Shape_vtable), &p, &c); Color_destroy(&c); Point_destroy(&p); return s; } // destructors void Shape_destroy(const Shape* s) { Color_destroy(Shape_color(s)); Point_destroy(Shape_point(s)); } void Shape_delete(const Shape* s) { Shape_destroy(s); free((void*)s); } > cat Circle.h #ifndef GUARD_Circle_h #define GUARD_Circle_h 1 #include typedef struct Circle { Shape S; // public base class double R; // radius } Circle; // functions const Shape* Circle_shape(const Circle* c); double Circle_radius(const Circle* c); void actualCircle_draw(const Circle* c); double actualCircle_area(const Circle* c); void Circle_draw(const Circle* c); // virtual function double Circle_area(const Circle* c); // virtual function Circle* Circle_initialize(Circle* c, const Shape* s, double r); // constructors Circle Circle_createDefault(void); Circle Circle_createExplicit(const Shape* s, double r); Circle* Circle_newDefault(void); Circle* Circle_newExplicit(const Shape* s, double r); // destructors void Circle_destroy(const Circle* c); void Circle_delete(const Circle* c); #endif // GUARD_Circle_h > cat Circle.c // gcc -Wall -std=c99 -pedantic -I. -O2 -c Circle.c #include #include #include #include // functions const Shape* Circle_shape(const Circle* c) { return &(c->S); } double Circle_radius(const Circle* c) { return c->R; } void actualCircle_draw(const Circle* c) { fprintf(stderr, "Circle_draw(const Circle*)\n"); fflush(stderr); } double actualCircle_area(const Circle* c) { const double pi = 3.14159265358979323846; const double r = Circle_radius(c); fprintf(stderr, "Circle_area(const Circle*)\n"); fflush(stderr); return pi*r*r; } typedef struct Circle_vtable_t { void (*Circle_draw)(const Circle*); double (*Circle_area)(const Circle*); } Circle_vtable_t; static const Circle_vtable_t Circle_vtable = {actualCircle_draw, actualCircle_area}; void Circle_draw(const Circle* c) { // virtual function ((Circle_vtable_t*)(c->S.V))->Circle_draw(c); } double Circle_area(const Circle* c) { // virtual function return ((Circle_vtable_t*)(c->S.V))->Circle_area(c); } Circle* Circle_initialize(Circle* c, const Shape* s, double r) { Shape_initialize(&(c->S), (void*)(&Circle_vtable), Shape_point(s), Shape_color(s)); c->R = r; return c; } // constructors Circle Circle_createExplicit(const Shape* s, double r) { Circle c; Circle_initialize(&c, s, r); return c; } Circle Circle_createDefault(void) { Circle c; const Shape s = Shape_createDefault(); Circle_initialize(&c, &s, 0.0); Shape_destroy(&s); return c; } Circle* Circle_newExplicit(const Shape* s, double r) { Circle* c = (Circle*)malloc(sizeof(Circle)); Circle_initialize(c, s, r); return c; } Circle* Circle_newDefault(void) { Circle* c = (Circle*)malloc(sizeof(Circle)); const Shape s = Shape_createDefault(); Circle_initialize(c, &s, 0.0); Shape_destroy(&s); return c; } // destructors void Circle_destroy(const Circle* c) { Shape_destroy(Circle_shape(c)); } void Circle_delete(const Circle* c) { Shape_destroy(Circle_shape(c)); free((void*)c); } > cat main.c // gcc -Wall -std=c99 -pedantic -I. -O2 -o main main.c Circle.o Shape.o Color.o Point.o #include #include int main(int argc, char* argv[]) { const Shape s = Shape_createDefault(); const Circle c = Circle_createExplicit(&s, 2.0); Shape_draw((const Shape*)(&c)); fprintf(stdout, "%g = radius\t %g = area\n", Circle_radius(&c), Shape_area((const Shape*)(&c))); return 0; } > cat Makefile CC=gcc DEFINES= INCLUDE=-I. OPTIONS=-Wall -std=c99 -pedantic -O2 LIBRARY= OBJECTS=Point.o Color.o Shape.o Circle.o SOURCES=Point.c Color.c Shape.c Circle.c HEADERS=Point.h Color.h Shape.h Circle.h library= COMPILE=$(CC) $(DEFINES) $(INCLUDE) $(LIBRARY) $(OPTIONS) main: $(HEADERS) $(OBJECTS) main.c $(COMPILE) -o main main.c $(OBJECTS) $(library) Point.o: Point.h Point.c $(COMPILE) -c Point.c Color.o: Color.h Color.c $(COMPILE) -c Color.c Shape.o: Shape.h Shape.c $(COMPILE) -c Shape.c Circle.o: Circle.h Circle.c $(COMPILE) -c Circle.c clean: rm -f main $(OBJECTS)