Simulating inheritance and non-member functions in C

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;
}
 
T

The Real OS/2 Guy

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;

violating the namespace of the implementation.
typedef struct object {
/* Why use a union will become clear later */
union {
_object _object;

Hm, is your implemenation really happy with names starting with
underscore? You are sure that this name will not be used by the next
revision of it?
} 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;

a null statement lives as null statement independant of how many casts
you writes.
}
#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;

Another time you violates the namespace of your implementation.
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))

It's bad style to define macros as all lowercase. All uppercase is
standard.
int main (void)
{
object myobject, yourobject;

There is no type object as you've ony defined type _object.
button mybutton;

You've neither typedef#d nor defined type button. You should never
violate the namespace of your application, then you would hoenly avoid
mistypes as such.
 
S

Sheldon Simms

It's bad style to define macros as all lowercase. All uppercase is
standard.

Quick, somebody tell the C standards commitee. Not only did they
forget to standardize this rule, they've broken it themselves.
There is no type object as you've ony defined type _object.

You must have missed this part:
You've neither typedef#d nor defined type button.

You must have missed this part:
 
M

Mark McIntyre

Quick, somebody tell the C standards commitee.

That was "standard" with a small s, not a capital S. Perhaps
"recommended practice" is a better word.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top