For this particular example what you seem to really want is the ability to have a function pointer that points to two different functions, one to implement flying and one that implements not flying.
So the approach I would consider would be something like the following. I have not tried to actually compile this code but the sense of this is correct.
Also in your comments you mentioned about preventing changing the function pointer. You can do something like the following where a const
is added to the struct definition for the function pointer and then using a clone of the struct with a cast.
Header file flying.h contents.
typedef struct _TAG_Being {
int (* const printFlying)();
} Being;
Being * new_flyingThing ();
Being * new_Thing();
Implementation or flying.c file.
#include "flying.h"
static int printFlyingThing()
{
printf (" I am a flying thing\n");
return 0;
}
static int printThing()
{
printf (" I am a thing\n");
return 1;
}
// use the same layout and members as Being above.
typedef struct {
int (* printFlying)();
} BeingX;
Being * new_flyingThing ()
{
BeingX *p = malloc(sizeof(BeingX));
p->printFlying = printFlyingThing; // use the flying thing function
{
Being *q = (Being *)p;
return q;
}
}
Being * new_Thing()
{
BeingX *p = malloc(sizeof(BeingX));
p->printFlying = printThing; // use the not flying thing function.
{
Being *q = (Being *)p;
return q;
}
}
Main or using .c file
#include "flying.h"
int main(){
Being * flyingThing = new_flyingThing();
Being * thingThatCantFly = new_Thing();
flyingThing->printFlying(); /* "I'm flying!" */
thingThatCantFly->printFlying(); /* "I can't fly!" */
}
If you have a need to access the actual Being
object or variable in the printFlying()
function then you will need to pass it as an argument.
For instance:
typedef struct _TAG_Being {
int xx;
int (*printFlying)(struct _TAG_Being *p);
} Being;
Then you would need something like:
Being * flyingThing = new_flyingThing();
flyingThing->printFlying(flyingThing); /* "I'm flying!" */