In last article, we saw an example of polymorphism in which method of parent object
is overloaded in child object. To extend the idea of abstract data type
and polymorphism, can we come out with an equal_to function
that can do comparison of sphere with sphere, csphere with csphere
and also sphere with csphere ?!
Yes, we are talking about function like int polymorphic_equal_to( void*, void*) !
The main hurdle in implementing it in both C and C++ is that "real"
type of object will not be known inside function and so we will not
know exactly how to process the comparison. C++ does provide "dynamic cast"
with which type of object can be determined by casting. Below is an example
of such implementation in C (which can also be used for C++ if any one do not
want to use dynamic cast):
File: sphere.h
#define SPHERE_NAME "sphere" typedef struct sphere_struct sphere; struct sphere_struct { const char *name; int (*get_radius)(sphere*); int (*equal_to)(sphere*, sphere*); int radius; }; void sphere_constructor(sphere* sptr, int rad); File: csphere.h #include "sphere.h" #define CSPHERE_COL_LEN 4 #define CSPHERE_NAME "csphere" typedef struct csphere_struct csphere; struct csphere_struct { const char *name; sphere *parent_sphere; int (*get_radius)(csphere*); const char *(*get_color)(csphere*); int (*equal_to)(csphere*, csphere*); char color[CSPHERE_COL_LEN]; }; void csphere_constructor(csphere* csptr, int rad, const char *col); static int sphere_equal_to_csphere( sphere *sptr, csphere *csptr ); int polymorphic_equal_to( void *s1, void *s2 ); File: sphere.c #include "sphere.h" static int intern_get_radius(sphere *sptr); static int intern_equal_to(sphere *s1, sphere *s2); void sphere_constructor(sphere *sptr, int rad) { sptr->name = SPHERE_NAME; sptr->get_radius = intern_get_radius; sptr->equal_to = intern_equal_to; sptr->radius = rad; } int intern_get_radius(sphere *sptr) { return sptr->radius; } int intern_equal_to(sphere *s1, sphere *s2) { return (s1->radius == s2->radius); } File: csphere.c #include "csphere.h" #include <string.h> static int intern_get_radius(csphere *csptr); static const char *intern_get_color(csphere *csptr); static int intern_equal_to(csphere *cs1, csphere *cs2); void csphere_constructor(csphere *csptr, int rad, const char *col) { csptr->name = CSPHERE_NAME; csptr->parent_sphere = (sphere*)malloc( sizeof( sphere ) ); sphere_constructor(csptr->parent_sphere, rad); strncpy( csptr->color, col, CSPHERE_COL_LEN-1 ); csptr->color[CSPHERE_COL_LEN-1] = '\0'; csptr->get_color = intern_get_color; csptr->get_radius = intern_get_radius; csptr->equal_to = intern_equal_to; } const char *intern_get_color(csphere* csptr) { return csptr->color; } int intern_get_radius(csphere *csptr) { return csptr->parent_sphere->radius; } int intern_equal_to(csphere *cs1, csphere *cs2) { return( (cs1->parent_sphere->equal_to(cs1->parent_sphere, cs2->parent_sphere) ) && !(strcmp(cs1->color, cs2->color)) ); } int sphere_equal_to_csphere( sphere *sptr, csphere *csptr ) { return (sptr->radius == csptr->parent_sphere->radius); } int polymorphic_equal_to( void *s1, void *s2 ) { sphere *sptr; sphere *sphere1; csphere *csphere1; sptr = (sphere *)s1; if( !strcmp( sptr->name, SPHERE_NAME ) ) { /* S1-SPHERE */ sphere1 = (sphere *)s1; sptr = (sphere *)s2; if( !strcmp( sptr->name, SPHERE_NAME ) ) { /* S1 & S2-SPHERE */ return sphere1->equal_to( sphere1, (sphere*)s2 ); } else { if( !strcmp( sptr->name, CSPHERE_NAME ) ) { /* S1-SPHERE & S2-CSPHERE */ return sphere_equal_to_csphere( sphere1, (csphere*)s2 ); } } } else { if( !strcmp( sptr->name, CSPHERE_NAME ) ) { /* S1-CSPHERE */ csphere1 = (csphere *)s1; sptr = (sphere *)s2; if( !strcmp( sptr->name, CSPHERE_NAME ) ) { /* S1 & S2-CSPHERE */ return csphere1->equal_to( csphere1, (csphere*)s2 ); } else { if( !strcmp( sptr->name, SPHERE_NAME ) ) { /* S1-CSPHERE & S2-SPHERE */ return sphere_equal_to_csphere( (sphere*)s2, csphere1 ); } } } } return 0; } File: spheremain.c #include <stdio.h> #include "csphere.h" int main(void) { sphere *sphere1 = (sphere*)malloc( sizeof( sphere ) ); csphere *csphere1 = (csphere*)malloc( sizeof( csphere ) ); sphere *sphere2 = (sphere*)malloc( sizeof( sphere ) ); csphere *csphere2 = (csphere*)malloc( sizeof( csphere ) ); sphere_constructor(sphere1, 30); csphere_constructor(csphere1, 20, "red"); sphere_constructor(sphere2, 20); csphere_constructor(csphere2, 30, "red"); printf( "Sphere 1 of radius %d\n", sphere1->get_radius(sphere1) ); printf( "Colored sphere 1 of radius %d and color %s\n", csphere1->get_radius(csphere1), csphere1->get_color(csphere1) ); printf( "Sphere 2 of radius %d\n", sphere1->get_radius(sphere2) ); printf( "Colored sphere 2 of radius %d and color %s\n", csphere2->get_radius(csphere2), csphere2->get_color(csphere2) ); if( sphere1->equal_to( sphere1, sphere2 ) ) { printf( "Sphere 1 is equal to sphere 2\n" ); } else { printf( "Sphere 1 is *not* equal to sphere 2\n" ); } if( csphere1->equal_to( csphere1, csphere2 ) ) { printf( "Colored sphere 1 is equal to colored sphere 2\n" ); } else { printf( "Colored sphere 1 is *not* equal to colored sphere 2\n" ); } printf( "Using polymorphic_equal_to ....\n" ); if( polymorphic_equal_to( (void*)sphere1, (void*)sphere2 ) ) { printf( "Sphere 1 is equal to sphere 2\n" ); } else { printf( "Sphere 1 is *not* equal to sphere 2\n" ); } if( polymorphic_equal_to( (void*)csphere1, (void*)csphere2 ) ) { printf( "Colored sphere 1 is equal to colored sphere 2\n" ); } else { printf( "Colored sphere 1 is *not* equal to colored sphere 2\n" ); } if( polymorphic_equal_to( (void*)csphere1, (void*)sphere2 ) ) { printf( "Colored sphere 1 is equal to sphere 2\n" ); } else { printf( "Colored sphere 1 is *not* equal to sphere 2\n" ); } if( polymorphic_equal_to( (void*)sphere1, (void*)csphere2 ) ) { printf( "Sphere 1 is equal to colored sphere 2\n" ); } else { printf( "Sphere 1 is *not* equal to colored sphere 2\n" ); } return 1; } |
References: For OOP concepts - An introduction to OOP by Timothy Budd.
Copyright © Samir Amberkar 2010-11 | § |
Object Oriented Programming using C « | C guide Index | . |