D
Doug Eleveld
Hi Everyone,
I have been playing aroung with 'object-oriented' C for a while now
and I have come up with an interesting way to simulate C++ inheritance
and non-member functions in C in a 100% typesafe way. The object
derivation is a bit cloudy, but the code is fairly repetitive and
doesn't seem to be terribly error prone. Maybe some clever macros
could clean up the repetitive code a bit.
Can any of you please comment on possible non-obvious pitfalls from
using this approach? All comments are welcome. Espesially clever
macros that can reduce the amount or repetitiveness in the code.
Or maybe you could tell what is wrong or dangerous with this approach.
Thanks very much,
Doug Eleveld
/* The base object 'class'------------------------- */
typedef struct _object {
/* Some variables */
} _object;
typedef struct object {
/* Why use a union will become clear later */
union {
_object _object;
} base;
} object;
/* A convenience macro for getting a object base class from a derived class */
#define OBJECT(obj) &((obj)->base._object)
/* Some example functions and convenience macros for objects ------------ */
void _attach(_object * obj, _object * parent)
{
/* Do something special here */
(void) obj;
(void) parent;
}
#define attach(obj,par) _attach(OBJECT(obj), OBJECT(par))
void _detach(_object * obj)
{
/* Do something special here */
(void) obj;
}
#define detach(obj) _detach(OBJECT(obj))
/* Deriving a button class from the object -------- */
typedef struct _button {
/* This is the base class we 'derive from */
union {
_object _object;
} base;
/* Some variables */
int selected;
} _button;
typedef struct button {
union {
_button _button;
_object _object; /* Here we list all the 'public' base classes */
} base;
} button;
/* A convenience macro for getting a button base class from a derived class */
#define BUTTON(btn) &((btn)->base._button)
/* Some example functions and convenience macros for buttons ------------- */
void _select(_button * btn)
{
btn->selected = 1;
}
#define select(btn) _select(BUTTON(btn))
void _deselect(_button * btn)
{
btn->selected = 0;
}
#define deselect(btn) _deselect(BUTTON(btn))
int main (void)
{
object myobject, yourobject;
button mybutton;
/* We can call 'non-member' functions on object */
/* This is typesafe */
attach(&myobject, &yourobject);
detach(&myobject);
detach(&yourobject);
/* We can call button functions for button */
/* This is typesafe */
select(&mybutton);
/* We can also call base class functions on button */
/* This is typesafe */
attach(&mybutton, &myobject);
return 0;
}
I have been playing aroung with 'object-oriented' C for a while now
and I have come up with an interesting way to simulate C++ inheritance
and non-member functions in C in a 100% typesafe way. The object
derivation is a bit cloudy, but the code is fairly repetitive and
doesn't seem to be terribly error prone. Maybe some clever macros
could clean up the repetitive code a bit.
Can any of you please comment on possible non-obvious pitfalls from
using this approach? All comments are welcome. Espesially clever
macros that can reduce the amount or repetitiveness in the code.
Or maybe you could tell what is wrong or dangerous with this approach.
Thanks very much,
Doug Eleveld
/* The base object 'class'------------------------- */
typedef struct _object {
/* Some variables */
} _object;
typedef struct object {
/* Why use a union will become clear later */
union {
_object _object;
} base;
} object;
/* A convenience macro for getting a object base class from a derived class */
#define OBJECT(obj) &((obj)->base._object)
/* Some example functions and convenience macros for objects ------------ */
void _attach(_object * obj, _object * parent)
{
/* Do something special here */
(void) obj;
(void) parent;
}
#define attach(obj,par) _attach(OBJECT(obj), OBJECT(par))
void _detach(_object * obj)
{
/* Do something special here */
(void) obj;
}
#define detach(obj) _detach(OBJECT(obj))
/* Deriving a button class from the object -------- */
typedef struct _button {
/* This is the base class we 'derive from */
union {
_object _object;
} base;
/* Some variables */
int selected;
} _button;
typedef struct button {
union {
_button _button;
_object _object; /* Here we list all the 'public' base classes */
} base;
} button;
/* A convenience macro for getting a button base class from a derived class */
#define BUTTON(btn) &((btn)->base._button)
/* Some example functions and convenience macros for buttons ------------- */
void _select(_button * btn)
{
btn->selected = 1;
}
#define select(btn) _select(BUTTON(btn))
void _deselect(_button * btn)
{
btn->selected = 0;
}
#define deselect(btn) _deselect(BUTTON(btn))
int main (void)
{
object myobject, yourobject;
button mybutton;
/* We can call 'non-member' functions on object */
/* This is typesafe */
attach(&myobject, &yourobject);
detach(&myobject);
detach(&yourobject);
/* We can call button functions for button */
/* This is typesafe */
select(&mybutton);
/* We can also call base class functions on button */
/* This is typesafe */
attach(&mybutton, &myobject);
return 0;
}