Skip to content

Instantly share code, notes, and snippets.

@ryjen
Last active November 19, 2015 06:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryjen/4180753 to your computer and use it in GitHub Desktop.
Save ryjen/4180753 to your computer and use it in GitHub Desktop.
Poor Man's Polymorphism in C
/**
*
* Poor mans polymorphism
*
* c0der78 (www.arg3.com)
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct vehicle Vehicle;
typedef struct car Car;
typedef struct plane Plane;
/**
* The "Base" structure
* sub structures must implement the exact type and order to cast it
*/
struct vehicle
{
int key;
void (*onStart)(Vehicle *);
};
/**
* Has the same field order as Vehicle plus additional info
*/
struct car
{
int key;
void (*onStart)(Vehicle *);
int doors;
int tires;
};
/**
* Has the same field order as Vehicle plus additional info
*/
struct plane
{
int key;
void (*onStart)(Vehicle *);
int engines;
};
/**
* This handles common code between a Car and a Plane
*/
void start_vehicle(Vehicle *this, int key, const char *vehicleName, const char *keyName)
{
// check for the right key
if(this->key == key) {
printf("%s fits %s\n", keyName, vehicleName);
this->onStart(this);
}
else
{
printf("%s does not fit %s\n", keyName, vehicleName);
}
}
/**
* callback when a car is started
*/
void car_started(Vehicle *this)
{
// cast back to a car
Car *car = (Car*) this;
printf("the car has %d doors and %d tires\n", car->doors, car->tires);
}
/**
* callback when a plane is started
*/
void plane_started(Vehicle *this)
{
// cast back to a plane
Plane *plane = (Plane *) this;
printf("the plane has %d engines\n", plane->engines);
}
/**
* Output:
*
* key1 fits volkswagon
* the car has 4 doors and 4 tires
* key2 does not fit volkswagon
* key1 does not fit b52
* key2 fits b52
* the plane has 6 engines
*/
int main(int argc, char *argv[])
{
srand(time(0));
int key1 = rand() % 10000 + 1;
int key2 = rand() % 10000 + 1;
// init a car
Car volkswagon;
volkswagon.key = key1;
volkswagon.doors = 4;
volkswagon.tires = 4;
volkswagon.onStart = car_started;
// init a plane
Plane b52;
b52.key = key2;
b52.engines = 6;
b52.onStart = plane_started;
// test. this is really what the magic is all about. We can cast a Car structure
// to a Vehicle structure because the field type and order is the same
start_vehicle((Vehicle*) &volkswagon, key1, "volkswagon", "key1");
start_vehicle((Vehicle*) &volkswagon, key2, "volkswagon", "key2");
// again we can cast a Plane structure to a Vehicle structure because
// the field type and order is the same
start_vehicle((Vehicle*) &b52, key1, "b52", "key1");
start_vehicle((Vehicle*) &b52, key2, "b52", "key2");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment