Re: Object-oriented programming in standard ANSI C
Thierry Chappuis wrote:
Please find attached a C implementation
of Bjarne Stroustrup's famous Shape class.
C is not an object oriented programming language
but you can write object oriented programs in C
including programs that implement run-time polymorphism.
The fprintf function on type *FILE is an example.
You don't need a language translator or a special library.
A program is not an object oriented programming language
just because it is written in an object oriented programming language.
All the popular object oriented programming languages are
procedural programming languages first.
An object oriented program must actually use
the object oriented features of the language.
Object oriented programming is first of all a programming style.
The problem with C is that it does not directly support features
such as inheritance and run-time polymorphism. Good C programmers
have always used an object oriented programming style
but implementing object oriented programs in C is problematic --
tedious and error prone. The C++ programming language provides
direct support for object oriented programming
so it is much easier and more reliable.
#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_initializ e(Point* p, double x, double y);
// constructors
Point
Point_createExp licit(double x, double y);
Point
Point_createDef ault(void);
Point*
Point_newExplic it(double x, double y);
Point*
Point_newDefaul t(void);
// destructors
void
Point_destroy(c onst Point* p);
void
Point_delete(co nst Point* p);
#endif // GUARD_Point_h
// gcc -Wall -std=c99 -pedantic -I. -O2 -c Point.c
#include<Point. h>
#include<stdlib .h>
// functions
double
Point_x(const Point* p) {
return p->X; }
double
Point_y(const Point* p) {
return p->Y; }
Point*
Point_initializ e(Point* p, double x, double y) {
p->X = x;
p->Y = y;
return p;
}
// constructors
Point
Point_createExp licit(double x, double y) {
Point p;
Point_initializ e(&p, x, y);
return p;
}
Point
Point_createDef ault(void) {
return Point_createExp licit(0.0, 0.0); }
Point*
Point_newExplic it(double x, double y) {
Point* p = (Point*)malloc( sizeof(Point));
Point_initializ e(p, x, y);
return p; }
Point*
Point_newDefaul t(void) {
return Point_newExplic it(0.0, 0.0); }
// destructors
void
Point_destroy(c onst Point* p) { }
void
Point_delete(co nst Point* p) {
Point_destroy(p );
free((void*)p); }
#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(con st Color *c);
unsigned int
Color_blue(cons t Color *c);
Color*
Color_initializ e(Color* c,
unsigned int r,
unsigned int g,
unsigned int b);
// constructors
Color
Color_createExp licit(
unsigned int r,
unsigned int g,
unsigned int b);
Color
Color_createDef ault(void);
Color*
Color_newExplic it(
unsigned int r,
unsigned int g,
unsigned int b);
Color*
Color_newDefaul t(void);
// destructor
void
Color_destroy(c onst Color *c);
void
Color_delete(co nst Color *c);
#endif // GUARD_Color_h
// gcc -Wall -std=c99 -pedantic -I. -O2 -c Color.c
#include<Color. h>
#include<stdlib .h>
// functions
unsigned int
Color_red(const Color *c) {
return c->R; }
unsigned int
Color_green(con st Color *c) {
return c->G; }
unsigned int
Color_blue(cons t Color *c) {
return c->B; }
Color*
Color_initializ e(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_createExp licit(
unsigned int r,
unsigned int g,
unsigned int b) {
Color c;
Color_initializ e(&c, r, g, b);
return c; }
Color
Color_createDef ault(void) {
return Color_createExp licit(0, 0, 0); }
Color*
Color_newExplic it(
unsigned int r,
unsigned int g,
unsigned int b) {
Color* c = (Color*)malloc( sizeof(Color));
Color_initializ e(c, r, g, b);
return c; }
Color*
Color_newDefaul t(void) {
return Color_newExplic it(0, 0, 0); }
// destructors
void
Color_destroy(c onst Color *c) { }
void
Color_delete(co nst Color *c) {
Color_destroy(c );
free((void*)c); }
#ifndef GUARD_Shape_h
#define GUARD_Shape_h 1
#include<Point. h>
#include<Color. h>
typedef struct Shape {
// representation
const
void* V; // virtual function table pointer
Point P;
Color C;
} Shape;
// functions
const Point*
Shape_point(con st Shape* s);
const Color*
Shape_color(con st Shape* s);
void
actualShape_dra w(const Shape* s);
double
actualShape_are a(const Shape* s);
void
Shape_draw(cons t Shape* s); // virtual function
double
Shape_area(cons t Shape* s); // virtual function
Shape*
Shape_initializ e(Shape* s,
const void* v,
const Point* p,
const Color* c);
// constructors
Shape
Shape_createExp licit(
const Point* p,
const Color* c);
Shape
Shape_createDef ault(void);
Shape*
Shape_newExplic it(
const Point* p,
const Color* c);
Shape*
Shape_newDefaul t(void);
// destructors
void
Shape_destroy(c onst Shape* s);
void
Shape_delete(co nst Shape* s);
#endif // GUARD_Shape_h
// gcc -Wall -std=c99 -pedantic -I. -O2 -c Shape.c
#include<stdio. h>
#include<Shape. h>
#include<stdlib .h>
// functions
const Point*
Shape_point(con st Shape* s) {
return &(s->P); }
const Color*
Shape_color(con st Shape* s) {
return &(s->C); }
void
actualShape_dra w(const Shape* s) {
fprintf(stderr, "Shape_draw(con st Shape*)\n");
fflush(stderr); }
double
actualShape_are a(const Shape* s) {
fprintf(stderr, "Shape_area(con st Shape*)\n");
fflush(stderr);
return 0.0; }
typedef struct Shape_vtable_t {
void (*Shape_draw)(c onst Shape*);
double (*Shape_area)(c onst Shape*);
} Shape_vtable_t;
static const
Shape_vtable_t
Shape_vtable = {actualShape_dr aw, actualShape_are a};
void
Shape_draw(cons t Shape* s) { // virtual function
((Shape_vtable_ t*)(s->V))->Shape_draw(s ); }
double
Shape_area(cons t Shape* s) { // virtual function
return ((Shape_vtable_ t*)(s->V))->Shape_area(s ); }
Shape*
Shape_initializ e(Shape* s,
const
void* v,
const
Point* p,
const
Color* c) {
s->V = v;
Point_initializ e(&(s->P), Point_x(p), Point_y(p));
Color_initializ e(&(s->C), Color_red(c), Color_green(c), Color_blue(c));
return s; }
// constructors
Shape
Shape_createExp licitShape(
const Point* p,
const Color* c) {
Shape s;
Shape_initializ e(&s, (const void*)(&Shape_v table), p, c);
return s; }
Shape
Shape_createDef ault(void) {
Shape s;
Point p = Point_createDef ault();
Color c = Color_createDef ault();
Shape_initializ e(&s, (const void*)(&Shape_v table), &p, &c);
Color_destroy(& c);
Point_destroy(& p);
return s; }
Shape*
Shape_newExplic itShape(
const Point* p,
const Color* c) {
Shape* s = (Shape*)malloc( sizeof(Shape));
Shape_initializ e(s, (const void*)(&Shape_v table), p, c);
return s; }
Shape*
Shape_newDefaul t(void) {
Shape* s = (Shape*)malloc( sizeof(Shape));
Point p = Point_createDef ault();
Color c = Color_createDef ault();
Shape_initializ e(s, (const void*)(&Shape_v table), &p, &c);
Color_destroy(& c);
Point_destroy(& p);
return s; }
// destructors
void
Shape_destroy(c onst Shape* s) {
Color_destroy(S hape_color(s));
Point_destroy(S hape_point(s));
}
void
Shape_delete(co nst Shape* s) {
Shape_destroy(s );
free((void*)s); }
#ifndef GUARD_Circle_h
#define GUARD_Circle_h 1
#include<Shape. h>
typedef struct Circle {
Shape S; // public base class
double R; // radius
} Circle;
// functions
const Shape*
Circle_shape(co nst Circle* c);
double
Circle_radius(c onst Circle* c);
void
actualCircle_dr aw(const Circle* c);
double
actualCircle_ar ea(const Circle* c);
void
Circle_draw(con st Circle* c); // virtual function
double
Circle_area(con st Circle* c); // virtual function
Circle*
Circle_initiali ze(Circle* c, const Shape* s, double r);
// constructors
Circle
Circle_createDe fault(void);
Circle
Circle_createEx plicit(const Shape* s, double r);
Circle*
Circle_newDefau lt(void);
Circle*
Circle_newExpli cit(const Shape* s, double r);
// destructors
void
Circle_destroy( const Circle* c);
void
Circle_delete(c onst Circle* c);
#endif // GUARD_Circle_h
// gcc -Wall -std=c99 -pedantic -I. -O2 -c Circle.c
#include<math.h >
#include<stdio. h>
#include<Circle .h>
#include<stdlib .h>
// functions
const Shape*
Circle_shape(co nst Circle* c) {
return &(c->S); }
double
Circle_radius(c onst Circle* c) {
return c->R; }
void
actualCircle_dr aw(const Circle* c) {
fprintf(stderr, "Circle_draw(co nst Circle*)\n");
fflush(stderr); }
double
actualCircle_ar ea(const Circle* c) {
const
double pi = 3.1415926535897 9323846;
const
double r = Circle_radius(c );
fprintf(stderr, "Circle_area(co nst 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_d raw, actualCircle_ar ea};
void
Circle_draw(con st Circle* c) { // virtual function
((Circle_vtable _t*)(c->S.V))->Circle_draw(c) ;
}
double
Circle_area(con st Circle* c) { // virtual function
return ((Circle_vtable _t*)(c->S.V))->Circle_area(c) ;
}
Circle*
Circle_initiali ze(Circle* c, const Shape* s, double r) {
Shape_initializ e(&(c->S),
(void*)(&Circle _vtable),
Shape_point(s),
Shape_color(s)) ;
c->R = r;
return c; }
// constructors
Circle
Circle_createEx plicit(const Shape* s, double r) {
Circle c;
Circle_initiali ze(&c, s, r);
return c; }
Circle
Circle_createDe fault(void) {
Circle c;
const
Shape s = Shape_createDef ault();
Circle_initiali ze(&c, &s, 0.0);
Shape_destroy(& s);
return c; }
Circle*
Circle_newExpli cit(const Shape* s, double r) {
Circle* c = (Circle*)malloc (sizeof(Circle) );
Circle_initiali ze(c, s, r);
return c; }
Circle*
Circle_newDefau lt(void) {
Circle* c = (Circle*)malloc (sizeof(Circle) );
const
Shape s = Shape_createDef ault();
Circle_initiali ze(c, &s, 0.0);
Shape_destroy(& s);
return c; }
// destructors
void
Circle_destroy( const Circle* c) {
Shape_destroy(C ircle_shape(c)) ;
}
void
Circle_delete(c onst Circle* c) {
Shape_destroy(C ircle_shape(c)) ;
free((void*)c); }
// gcc -Wall -std=c99 -pedantic -I. -O2 -o main main.c Circle.o Shape.o Color.o Point.o
#include<stdio. h>
#include<Circle .h>
int
main(int argc, char* argv[]) {
const
Shape s = Shape_createDef ault();
const
Circle c = Circle_createEx plicit(&s, 2.0);
Shape_draw((con st Shape*)(&c));
fprintf(stdout, "%g = radius\t %g = area\n",
Circle_radius(& c), Shape_area((con st Shape*)(&c)));
return 0;
}
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)
Thierry Chappuis wrote:
I'm interested in techniques used to program in an object-oriented way
using the C ANSI language. I'm studying the GObject library and Laurent
Deniau's OOPC framework published on his web site at
http://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html. The approach is
very instructive. I know that I could do much of this stuff with e.g.
C++, but the intellectual challenge of implementing these concepts with
pure ANSI C is relevant to me.
>
Are you aware of another approaches? Any experience in using such
techniques in production code? The use of GObject seems to be well
implemented in the GNOME world, but I didn't find much about Laurent
Deniau's OOPC. Have you some comments about the strengths and drawbacks
of such techniques?
using the C ANSI language. I'm studying the GObject library and Laurent
Deniau's OOPC framework published on his web site at
http://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html. The approach is
very instructive. I know that I could do much of this stuff with e.g.
C++, but the intellectual challenge of implementing these concepts with
pure ANSI C is relevant to me.
>
Are you aware of another approaches? Any experience in using such
techniques in production code? The use of GObject seems to be well
implemented in the GNOME world, but I didn't find much about Laurent
Deniau's OOPC. Have you some comments about the strengths and drawbacks
of such techniques?
of Bjarne Stroustrup's famous Shape class.
C is not an object oriented programming language
but you can write object oriented programs in C
including programs that implement run-time polymorphism.
The fprintf function on type *FILE is an example.
You don't need a language translator or a special library.
A program is not an object oriented programming language
just because it is written in an object oriented programming language.
All the popular object oriented programming languages are
procedural programming languages first.
An object oriented program must actually use
the object oriented features of the language.
Object oriented programming is first of all a programming style.
The problem with C is that it does not directly support features
such as inheritance and run-time polymorphism. Good C programmers
have always used an object oriented programming style
but implementing object oriented programs in C is problematic --
tedious and error prone. The C++ programming language provides
direct support for object oriented programming
so it is much easier and more reliable.
cat 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_initializ e(Point* p, double x, double y);
// constructors
Point
Point_createExp licit(double x, double y);
Point
Point_createDef ault(void);
Point*
Point_newExplic it(double x, double y);
Point*
Point_newDefaul t(void);
// destructors
void
Point_destroy(c onst Point* p);
void
Point_delete(co nst Point* p);
#endif // GUARD_Point_h
cat Point.c
#include<Point. h>
#include<stdlib .h>
// functions
double
Point_x(const Point* p) {
return p->X; }
double
Point_y(const Point* p) {
return p->Y; }
Point*
Point_initializ e(Point* p, double x, double y) {
p->X = x;
p->Y = y;
return p;
}
// constructors
Point
Point_createExp licit(double x, double y) {
Point p;
Point_initializ e(&p, x, y);
return p;
}
Point
Point_createDef ault(void) {
return Point_createExp licit(0.0, 0.0); }
Point*
Point_newExplic it(double x, double y) {
Point* p = (Point*)malloc( sizeof(Point));
Point_initializ e(p, x, y);
return p; }
Point*
Point_newDefaul t(void) {
return Point_newExplic it(0.0, 0.0); }
// destructors
void
Point_destroy(c onst Point* p) { }
void
Point_delete(co nst Point* p) {
Point_destroy(p );
free((void*)p); }
cat 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(con st Color *c);
unsigned int
Color_blue(cons t Color *c);
Color*
Color_initializ e(Color* c,
unsigned int r,
unsigned int g,
unsigned int b);
// constructors
Color
Color_createExp licit(
unsigned int r,
unsigned int g,
unsigned int b);
Color
Color_createDef ault(void);
Color*
Color_newExplic it(
unsigned int r,
unsigned int g,
unsigned int b);
Color*
Color_newDefaul t(void);
// destructor
void
Color_destroy(c onst Color *c);
void
Color_delete(co nst Color *c);
#endif // GUARD_Color_h
cat Color.c
#include<Color. h>
#include<stdlib .h>
// functions
unsigned int
Color_red(const Color *c) {
return c->R; }
unsigned int
Color_green(con st Color *c) {
return c->G; }
unsigned int
Color_blue(cons t Color *c) {
return c->B; }
Color*
Color_initializ e(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_createExp licit(
unsigned int r,
unsigned int g,
unsigned int b) {
Color c;
Color_initializ e(&c, r, g, b);
return c; }
Color
Color_createDef ault(void) {
return Color_createExp licit(0, 0, 0); }
Color*
Color_newExplic it(
unsigned int r,
unsigned int g,
unsigned int b) {
Color* c = (Color*)malloc( sizeof(Color));
Color_initializ e(c, r, g, b);
return c; }
Color*
Color_newDefaul t(void) {
return Color_newExplic it(0, 0, 0); }
// destructors
void
Color_destroy(c onst Color *c) { }
void
Color_delete(co nst Color *c) {
Color_destroy(c );
free((void*)c); }
cat Shape.h
#define GUARD_Shape_h 1
#include<Point. h>
#include<Color. h>
typedef struct Shape {
// representation
const
void* V; // virtual function table pointer
Point P;
Color C;
} Shape;
// functions
const Point*
Shape_point(con st Shape* s);
const Color*
Shape_color(con st Shape* s);
void
actualShape_dra w(const Shape* s);
double
actualShape_are a(const Shape* s);
void
Shape_draw(cons t Shape* s); // virtual function
double
Shape_area(cons t Shape* s); // virtual function
Shape*
Shape_initializ e(Shape* s,
const void* v,
const Point* p,
const Color* c);
// constructors
Shape
Shape_createExp licit(
const Point* p,
const Color* c);
Shape
Shape_createDef ault(void);
Shape*
Shape_newExplic it(
const Point* p,
const Color* c);
Shape*
Shape_newDefaul t(void);
// destructors
void
Shape_destroy(c onst Shape* s);
void
Shape_delete(co nst Shape* s);
#endif // GUARD_Shape_h
cat Shape.c
#include<stdio. h>
#include<Shape. h>
#include<stdlib .h>
// functions
const Point*
Shape_point(con st Shape* s) {
return &(s->P); }
const Color*
Shape_color(con st Shape* s) {
return &(s->C); }
void
actualShape_dra w(const Shape* s) {
fprintf(stderr, "Shape_draw(con st Shape*)\n");
fflush(stderr); }
double
actualShape_are a(const Shape* s) {
fprintf(stderr, "Shape_area(con st Shape*)\n");
fflush(stderr);
return 0.0; }
typedef struct Shape_vtable_t {
void (*Shape_draw)(c onst Shape*);
double (*Shape_area)(c onst Shape*);
} Shape_vtable_t;
static const
Shape_vtable_t
Shape_vtable = {actualShape_dr aw, actualShape_are a};
void
Shape_draw(cons t Shape* s) { // virtual function
((Shape_vtable_ t*)(s->V))->Shape_draw(s ); }
double
Shape_area(cons t Shape* s) { // virtual function
return ((Shape_vtable_ t*)(s->V))->Shape_area(s ); }
Shape*
Shape_initializ e(Shape* s,
const
void* v,
const
Point* p,
const
Color* c) {
s->V = v;
Point_initializ e(&(s->P), Point_x(p), Point_y(p));
Color_initializ e(&(s->C), Color_red(c), Color_green(c), Color_blue(c));
return s; }
// constructors
Shape
Shape_createExp licitShape(
const Point* p,
const Color* c) {
Shape s;
Shape_initializ e(&s, (const void*)(&Shape_v table), p, c);
return s; }
Shape
Shape_createDef ault(void) {
Shape s;
Point p = Point_createDef ault();
Color c = Color_createDef ault();
Shape_initializ e(&s, (const void*)(&Shape_v table), &p, &c);
Color_destroy(& c);
Point_destroy(& p);
return s; }
Shape*
Shape_newExplic itShape(
const Point* p,
const Color* c) {
Shape* s = (Shape*)malloc( sizeof(Shape));
Shape_initializ e(s, (const void*)(&Shape_v table), p, c);
return s; }
Shape*
Shape_newDefaul t(void) {
Shape* s = (Shape*)malloc( sizeof(Shape));
Point p = Point_createDef ault();
Color c = Color_createDef ault();
Shape_initializ e(s, (const void*)(&Shape_v table), &p, &c);
Color_destroy(& c);
Point_destroy(& p);
return s; }
// destructors
void
Shape_destroy(c onst Shape* s) {
Color_destroy(S hape_color(s));
Point_destroy(S hape_point(s));
}
void
Shape_delete(co nst Shape* s) {
Shape_destroy(s );
free((void*)s); }
cat Circle.h
#define GUARD_Circle_h 1
#include<Shape. h>
typedef struct Circle {
Shape S; // public base class
double R; // radius
} Circle;
// functions
const Shape*
Circle_shape(co nst Circle* c);
double
Circle_radius(c onst Circle* c);
void
actualCircle_dr aw(const Circle* c);
double
actualCircle_ar ea(const Circle* c);
void
Circle_draw(con st Circle* c); // virtual function
double
Circle_area(con st Circle* c); // virtual function
Circle*
Circle_initiali ze(Circle* c, const Shape* s, double r);
// constructors
Circle
Circle_createDe fault(void);
Circle
Circle_createEx plicit(const Shape* s, double r);
Circle*
Circle_newDefau lt(void);
Circle*
Circle_newExpli cit(const Shape* s, double r);
// destructors
void
Circle_destroy( const Circle* c);
void
Circle_delete(c onst Circle* c);
#endif // GUARD_Circle_h
cat Circle.c
#include<math.h >
#include<stdio. h>
#include<Circle .h>
#include<stdlib .h>
// functions
const Shape*
Circle_shape(co nst Circle* c) {
return &(c->S); }
double
Circle_radius(c onst Circle* c) {
return c->R; }
void
actualCircle_dr aw(const Circle* c) {
fprintf(stderr, "Circle_draw(co nst Circle*)\n");
fflush(stderr); }
double
actualCircle_ar ea(const Circle* c) {
const
double pi = 3.1415926535897 9323846;
const
double r = Circle_radius(c );
fprintf(stderr, "Circle_area(co nst 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_d raw, actualCircle_ar ea};
void
Circle_draw(con st Circle* c) { // virtual function
((Circle_vtable _t*)(c->S.V))->Circle_draw(c) ;
}
double
Circle_area(con st Circle* c) { // virtual function
return ((Circle_vtable _t*)(c->S.V))->Circle_area(c) ;
}
Circle*
Circle_initiali ze(Circle* c, const Shape* s, double r) {
Shape_initializ e(&(c->S),
(void*)(&Circle _vtable),
Shape_point(s),
Shape_color(s)) ;
c->R = r;
return c; }
// constructors
Circle
Circle_createEx plicit(const Shape* s, double r) {
Circle c;
Circle_initiali ze(&c, s, r);
return c; }
Circle
Circle_createDe fault(void) {
Circle c;
const
Shape s = Shape_createDef ault();
Circle_initiali ze(&c, &s, 0.0);
Shape_destroy(& s);
return c; }
Circle*
Circle_newExpli cit(const Shape* s, double r) {
Circle* c = (Circle*)malloc (sizeof(Circle) );
Circle_initiali ze(c, s, r);
return c; }
Circle*
Circle_newDefau lt(void) {
Circle* c = (Circle*)malloc (sizeof(Circle) );
const
Shape s = Shape_createDef ault();
Circle_initiali ze(c, &s, 0.0);
Shape_destroy(& s);
return c; }
// destructors
void
Circle_destroy( const Circle* c) {
Shape_destroy(C ircle_shape(c)) ;
}
void
Circle_delete(c onst Circle* c) {
Shape_destroy(C ircle_shape(c)) ;
free((void*)c); }
cat main.c
#include<stdio. h>
#include<Circle .h>
int
main(int argc, char* argv[]) {
const
Shape s = Shape_createDef ault();
const
Circle c = Circle_createEx plicit(&s, 2.0);
Shape_draw((con st Shape*)(&c));
fprintf(stdout, "%g = radius\t %g = area\n",
Circle_radius(& c), Shape_area((con st Shape*)(&c)));
return 0;
}
cat Makefile
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)
Comment