M
Mike
Attached below is a file that implements polymorphism in C. It's
loosly based on the way Miro Samek describes it
(http://www.embedded.com/97/fe29712.htm). I found the article a
little confusing so I made some changes and came up with wat's
below. It appears to work, but I've written plenty of programs before
that seemed to work, but didn't. Anyone willing to take a look, and
check for correcness? I would also love to hear suggestions on how to
simplify, improve upon, or increase the power of this method.
-Goal-
To have an array containing various shapes, and draw (just print
statement in this app) them, without knowing what they are.
-Implementation-
structs are used as classes.
A base class, shape_t is inherited by child classes, circle_t and
rectangle_t.
Inheritance is accomplished by including shape_t as the first member
in the childs structure (it has to be first).
A generic class is created, any_shape_t. A pointer of any_shape_t
type, can point to objects of type circle_t and rectangle_t.
Objects created must in initialized by a constuctor function.
This file was tested with GCC (with no warnings) on Linux.
Dumping what's below into a single file should do the trick.
This is the output I got:
Draw a circle of radius 17.
Draw a rectangle of length 6 and width 5.
/********************* source *******************/
#include <stdio.h>
typedef struct
{
void (*Draw)();
}shape_t, *p_shape_t;
typedef struct
{
shape_t shape;
}any_shape_t;
typedef struct
{
shape_t shape;
int radius;
}circle_t;
typedef struct
{
shape_t shape;
int length;
int width;
}rectangle_t;
circle_t* Circle_ctor(circle_t* p_c, int radius);
void Circle_draw(circle_t* p_c);
rectangle_t* Rectangle_ctor(rectangle_t* p_r, int length, int width);
void Rectangle_draw(rectangle_t* p_r);
/********* circle *********/
circle_t* Circle_ctor(circle_t* p_c, int radius)
{
p_c->radius = radius;
p_c->shape.Draw = Circle_draw;
return p_c;
}
void Circle_draw(circle_t* p_c)
{
printf("Draw a circle of radius %d.\n", p_c->radius);
}
/********* rectangle *********/
rectangle_t* Rectangle_ctor(rectangle_t* p_r, int length, int width)
{
p_r->length = length;
p_r->width = width;
p_r->shape.Draw = Rectangle_draw;
return p_r;
}
void Rectangle_draw(rectangle_t* p_r)
{
printf("Draw a rectangle of length %d and width %d.\n", p_r->length, p_r->width);
}
/********* main *********/
int main()
{
circle_t c1;
circle_t* p_c1;
rectangle_t r1;
rectangle_t* p_r1;
any_shape_t* p_shapes[] = {0,0,0,0,0,0};
int i;
p_c1 = Circle_ctor(&c1, 17);
p_r1 = Rectangle_ctor(&r1, 6, 5);
p_shapes[0] = (any_shape_t*)p_c1;
p_shapes[1] = (any_shape_t*)p_r1;
for(i=0; p_shapes != 0; i++)
p_shapes->shape.Draw(p_shapes);
return 0;
}
loosly based on the way Miro Samek describes it
(http://www.embedded.com/97/fe29712.htm). I found the article a
little confusing so I made some changes and came up with wat's
below. It appears to work, but I've written plenty of programs before
that seemed to work, but didn't. Anyone willing to take a look, and
check for correcness? I would also love to hear suggestions on how to
simplify, improve upon, or increase the power of this method.
-Goal-
To have an array containing various shapes, and draw (just print
statement in this app) them, without knowing what they are.
-Implementation-
structs are used as classes.
A base class, shape_t is inherited by child classes, circle_t and
rectangle_t.
Inheritance is accomplished by including shape_t as the first member
in the childs structure (it has to be first).
A generic class is created, any_shape_t. A pointer of any_shape_t
type, can point to objects of type circle_t and rectangle_t.
Objects created must in initialized by a constuctor function.
This file was tested with GCC (with no warnings) on Linux.
Dumping what's below into a single file should do the trick.
This is the output I got:
Draw a circle of radius 17.
Draw a rectangle of length 6 and width 5.
/********************* source *******************/
#include <stdio.h>
typedef struct
{
void (*Draw)();
}shape_t, *p_shape_t;
typedef struct
{
shape_t shape;
}any_shape_t;
typedef struct
{
shape_t shape;
int radius;
}circle_t;
typedef struct
{
shape_t shape;
int length;
int width;
}rectangle_t;
circle_t* Circle_ctor(circle_t* p_c, int radius);
void Circle_draw(circle_t* p_c);
rectangle_t* Rectangle_ctor(rectangle_t* p_r, int length, int width);
void Rectangle_draw(rectangle_t* p_r);
/********* circle *********/
circle_t* Circle_ctor(circle_t* p_c, int radius)
{
p_c->radius = radius;
p_c->shape.Draw = Circle_draw;
return p_c;
}
void Circle_draw(circle_t* p_c)
{
printf("Draw a circle of radius %d.\n", p_c->radius);
}
/********* rectangle *********/
rectangle_t* Rectangle_ctor(rectangle_t* p_r, int length, int width)
{
p_r->length = length;
p_r->width = width;
p_r->shape.Draw = Rectangle_draw;
return p_r;
}
void Rectangle_draw(rectangle_t* p_r)
{
printf("Draw a rectangle of length %d and width %d.\n", p_r->length, p_r->width);
}
/********* main *********/
int main()
{
circle_t c1;
circle_t* p_c1;
rectangle_t r1;
rectangle_t* p_r1;
any_shape_t* p_shapes[] = {0,0,0,0,0,0};
int i;
p_c1 = Circle_ctor(&c1, 17);
p_r1 = Rectangle_ctor(&r1, 6, 5);
p_shapes[0] = (any_shape_t*)p_c1;
p_shapes[1] = (any_shape_t*)p_r1;
for(i=0; p_shapes != 0; i++)
p_shapes->shape.Draw(p_shapes);
return 0;
}