Hi,
I usually program in C++, but for a special project I do have to code in
C (because it may be ported to embedded-like platforms where no C++
compiler exists).
I do want to realize some kind of polymorphic behaviour, like this:
I have some abstract base "class" Base, that is, a struct containing a
vtable of function-pointers and possibly some common fields (but at the
moment, there aren't any such fields, if this does make a difference).
Then I need some concrete sub-classes, say A and B, implementing those
virtual methods and both having their own number of fields; I do not
need a more complicated class-hirarchy, only these two levels.
My main problem is how to structure the data combining common fields
(vtable) and the fields special to A or B. I did come up with two
methods, and would like to know what you suggest to be the better one
(or any other suggestions).
Method 1
========
typedef struct
{
void (*method)(void* me);
} vtable;
/* This is the base class, holding the common fields and a pointer to
the sub-class' data */
typedef struct
{
vtable* methods;
void* subclass;
} Base;
typedef struct
{
int field;
} A;
typedef struct
{
double field;
} B;
In the specific implementation of method, I'd cast the void* to A*/B* to
access the fields; however, this would mean that each object consisted
of *two* dynamically allocated blocks of memory. This additional
overhead is surely not a real performance problem in my case, but it
seems somewhat unneccessary complicated to me.
And it would require some more tricks (or at least an additional
argument to each virtual method) to have access to the vtable and
possible common fields.
Method 2
========
struct Base;
typedef struct
{
void (*method)(struct Base* me);
} vtable;
typedef struct
{
vtable* methods;
} Base;
typedef struct
{
Base base;
int field;
} A;
typedef struct
{
Base base;
float field;
} B;
Here, one would only allocate a single block of memory for A or B,
respectively, so that the Base instance is carried right with each
subclass. I do like this more in general; however, in each virtual
method, I'd have to case struct Base* me to A* me or B* me--this is the
point I'm unsure about.
Does the standard allow this, i.e., can I store an A* in a struct Base*
variable, and recast it back without any problems? Or might those two
pointers be different?
Could I use void* as argument in the second case, too, because void* is
required to hold *any* pointer?
I'm sure there is some elegant and portable solution... Thanks for your
advice!
Daniel
--
Got two Dear-Daniel-Instant Messages
by MSN, associate ICQ with stress--so
please use good, old E-MAIL!