Last week Quiz Overview Function Pointers Preparation for C++ Object Oriented C encapsulation reuse polymorphism in C --------------------------------------------------------- Function Pointers ================== sort example char *names[] = { "zack", "bob", "alice" } void bsort (char *v[], int size) { int i,j; for (i=0; i < size; i++) for (j = i+1; j < size; j++) if (strcmp (v[i], v[j]) > 0) swap (v[i], v[j]); } But now I have a struct struct person { char name[32]; int age; }; typedef int (*comp_fct) (void *, void *); void bsort (struct person *v[], int size) { int i,j; for (i=0; i < size; i++) for (j = i+1; j < size; j++) if (strcmp (v[i]->name, v[j]->name) > 0) swap (v[i], v[j]); } Note : Need only change compare function (the rest stays the same. What about if I wanted to sort on age, --> need to change the compare function typedef int (*comp_fct) (void *, void *); void bsort (void *v[], int size, comp_fct compare) { int i,j; for (i=0; i < size; i++) for (j = i+1; j < size; j++) if ((*compare) (v[i], v[j]) > 0) swap (v[i], v[j]); } int person_compare (void *v1, void *v2) { struct person *p1 = (struct person*)v1; struct person *p2 = (struct person*)v2; return strcmp (p1->name, p2->name); // or if (p1->age < p2->age) return -1; if (p1->age > p2->age) return 1; return 0; } Object Oriented C ================== What can we say about OO style programming Abstraction Encapsulation (information hiding) Hierarchy (code reuse) Polymorphism Start with classic example of OO programming Define an Object (type) and some methods that operate on the object. struct point { int x; int y; }; void point_move (struct point*, int dx, int dy); void point_draw (struct point*); point_init (struct point*p, int X, int Y) { p->x = X; p->y = Y; } point_init_P (struct point *p, int rad, int ang) { p->x = cos (ang)*rad; y = sin(ang)*rad; } Why go to this bother? How about? struct rect { struct point p1; struct point p2; }; void rect_init (struct rect*p, int l, int h) { point_init (p->p1, 0, 0); point_init (p->p2, l, h); } void rect_move (struct rect*p, int dx, int dy); void rect_draw (struct rect*p); We get code reuse and very easy to read code. Simulations Imagine you are writing an air trafic control Simulation. In the simulator you need to keep track of lot's planes. You are writing a test for the controllers to see if they react correctly. We need to have struct aircraft { Vector dir; int speed; Postion p; }; >>Each aircraft will have a way of moving void aircraft_set_direction (struct aircraft*, Vector newdir); void aircraft_move (struct aircraft*); void aircraft_draw (struct aircraft*); >>But now I need distinguish between frieght passenger . passenger_aircraft is a kind of aircraft and so frieght_aircraft >>I can say passenger aircarft is an aircraft and more... struct passenger_aircraft { struct aircraft air; int passengers; }; void passenger_aircraft_passengers(struct passenger_aircraft*, int p); and so on... >>But can use aircraft_move with a passenger aircraft? >>Draw the memory struct passenger_aircraft my_plane; aircraft_move (&my_plane.air); // or use cast passenger_aircraft_passengers (&my_plane, 8); >> Need to draw different colored aircraft void passenger_draw(struct passenger*); void frieghter_draw(struct frieghter*); But if I have an array of aircraft * how do I call the right one?? struct aircraft* planes[10] = { &my_plane, ... }; int p; for (p=0; p < 10; p++) { /* draw the plane */ } >> One way add a type code to each struct aircraft { vector ... ; int type ; }; enum airtype { PASSENGER, FRIEGHTER, PRIVATE }; >> Then add to loop if (planes[p]->air.type == PASSENGER) passenger_draw (planes[p]); ... >> Pretty good but if I add another kind of plane then I need >> fix all the code where I test the type... >> Would be best to store the kind of draw routine WITH the >> plane itself!!! typedef void (*airdraw)(struct aircraft*); struct aircraft { Vector dir; ...; airdraw drawer }; >> Then in the init routine passenger_init (struct passenger*p) { ... p->air.draw = passenger_draw; } >> I can then call any airplane to draw itself! (*plane->drawer) (plane); >> Substitute this into what we had before for (p=0; p < 10; p++) { (*planes[p]->drawer) (planes[p]); } >> Extra..Does anybody see a better way of storing the drawer >> pointer.