Sunday, October 7, 2007

Implementing polymorphism in C

It is about my project at Chulalongkorn University again. My instructor assigned a term project in course Operating System and System Programmingto my team. We have to create a program that simulates some concepts in operating system such as
  • Process creation
  • Process termination
  • Process Scheduling
  • Interrupts
  • Interprocess Communication
  • etc.
Other requirements are the program must be able to run on at least one kind of Unix or Linux systems and the program must be coded in pure C. We used Code::Blocks + Cygwin as our development environment (how to setup Code::Blocks and Cygwin to work together?). However, we compiled and presented our program on a Mac (which is a kind of Unix).

Let's get back to our topic. In our project, a process is represented by a worm moving around the screen. I want each type of worm to move differently.

If I were coding in Java, I would create a base class, named it Worm, and derived it to create other specific classes such as LeftWorm, RightWorm, RandomWorm. This is where polymorphism comes in handy.

How can I implement such high-level object-oriented mechanism in a pure low-level C program ?

The solution is to use pointers to functions. The following code is my code sample which shows how can each animal has different behaviors.

#include <stdio.h>
#include <stdlib.h>

#define DOG 1
#define CAT 2
#define FISH 3


struct
animal{
// animal's name
char *name;
// parameters: count, target's name; return type: void
void (*bark)(int, char*);
};


// typedef a pointer to animal struct
typedef struct animal* ANIMALPTR;

// animals' behaviors
void dogbark(int count, char *target){
int
i;
for
(i = 0 ; i < count ; i++){
printf("Box! %s ", target);
}

printf("\n");
}


void
catbark(int count, char *target){
int
i;
for
(i = 0 ; i < count ; i++){
printf("Meow~ %s ", target);
}

printf("\n");
}


void
fishbark(int count, char *target){
int
i;
for
(i = 0 ; i < count ; i++){
printf("(Cannot bark) %s ", target);
}

printf("\n");
}



ANIMALPTR get_animal(int type){
ANIMALPTR ret =
(
ANIMALPTR)malloc(sizeof(struct animal));
switch
(type){
case
DOG:
ret->name = "Dog";
ret->bark = dogbark;
break
;
case
CAT:
ret->name = "Cat";
ret->bark = catbark;
break
;
case
FISH:
ret->name = "Fish";
ret->bark = fishbark;
break
;
}
}


int
main()
{

int
i;
ANIMALPTR arr[3];
arr[0] = get_animal(DOG);
arr[1] = get_animal(FISH);
arr[2] = get_animal(CAT);
for
(i = 0 ; i < 3 ; i++){
printf("Animal: %s\n", arr[i]->name);
arr[i]->bark(2,"M3rlinez");
printf("\n");
}

return
0;
}
The following is this program's output.

Animal: Dog
Box! M3rlinez Box! M3rlinez

Animal: Fish
(Cannot bark) M3rlinez (Cannot bark) M3rlinez

Animal: Cat
Meow~ M3rlinez Meow~ M3rlinez


Press ENTER to continue.