P
Peter Michaux
/*
I want to have heterogeneous lists but treat all nodes the same
without checking some sort of struct "type" member and then using a
switch statement to call the appropriate function for that type. This
is in an effort to make my code more modular. Updating the switch
statement when a new "type" is added is not appealing. I've been
working on an idea (surely not original) about having polymorphic
struct "objects" that have function pointer members for "methods". My
code example is below and I would like to know where it sits in the
range from "hideous worst practice ever" to "yep people do that sort
of thing". If there are known improvements I could make I would
appreciate any comments, a link to a web page or book title.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct _Object {
void (*prettyPrint)(struct _Object *);
void (*destroy)(struct _Object *);
} Object;
/***********************************/
typedef struct _Number {
/* obj member must be first in this struct
for down casts of Number to Object */
Object obj;
double val;
} Number;
void prettyPrintNumber(Object *obj) {
Number *num = (Number *)obj;
printf("the number is: %g\n", num->val);
}
void destroyNumber(Object *obj) {
Number *num = (Number *)obj;
free(num);
}
Number *createNumber(double val) {
Number *num = (Number *)malloc(sizeof(Number));
num->obj.prettyPrint = prettyPrintNumber;
num->obj.destroy = destroyNumber;
num->val = val;
return num;
}
/***********************************/
typedef struct _String {
Object obj;
char *val;
} String;
void prettyPrintString(Object *obj) {
String *str = (String *)obj;
printf("the string is: %s\n", str->val);
}
void destroyString(Object *obj) {
String *str = (String *)obj;
free(str->val);
free(str);
}
String *createString(char *val) {
String *str = (String *)malloc(sizeof(String));
str->obj.prettyPrint = prettyPrintString;
str->obj.destroy = destroyString;
str->val = strdup(val);
return str;
}
/***********************************/
int main(void)
{
printf("hello, world\n");
Object *n = (Object *)createNumber(21);
/* don't need to know n is a Number to print it */
n->prettyPrint(n);
Object *s = (Object *)createString("test");
s->prettyPrint(s);
n->destroy(n);
s->destroy(s);
return 0;
}
/*
Thanks,
Peter
*/
I want to have heterogeneous lists but treat all nodes the same
without checking some sort of struct "type" member and then using a
switch statement to call the appropriate function for that type. This
is in an effort to make my code more modular. Updating the switch
statement when a new "type" is added is not appealing. I've been
working on an idea (surely not original) about having polymorphic
struct "objects" that have function pointer members for "methods". My
code example is below and I would like to know where it sits in the
range from "hideous worst practice ever" to "yep people do that sort
of thing". If there are known improvements I could make I would
appreciate any comments, a link to a web page or book title.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct _Object {
void (*prettyPrint)(struct _Object *);
void (*destroy)(struct _Object *);
} Object;
/***********************************/
typedef struct _Number {
/* obj member must be first in this struct
for down casts of Number to Object */
Object obj;
double val;
} Number;
void prettyPrintNumber(Object *obj) {
Number *num = (Number *)obj;
printf("the number is: %g\n", num->val);
}
void destroyNumber(Object *obj) {
Number *num = (Number *)obj;
free(num);
}
Number *createNumber(double val) {
Number *num = (Number *)malloc(sizeof(Number));
num->obj.prettyPrint = prettyPrintNumber;
num->obj.destroy = destroyNumber;
num->val = val;
return num;
}
/***********************************/
typedef struct _String {
Object obj;
char *val;
} String;
void prettyPrintString(Object *obj) {
String *str = (String *)obj;
printf("the string is: %s\n", str->val);
}
void destroyString(Object *obj) {
String *str = (String *)obj;
free(str->val);
free(str);
}
String *createString(char *val) {
String *str = (String *)malloc(sizeof(String));
str->obj.prettyPrint = prettyPrintString;
str->obj.destroy = destroyString;
str->val = strdup(val);
return str;
}
/***********************************/
int main(void)
{
printf("hello, world\n");
Object *n = (Object *)createNumber(21);
/* don't need to know n is a Number to print it */
n->prettyPrint(n);
Object *s = (Object *)createString("test");
s->prettyPrint(s);
n->destroy(n);
s->destroy(s);
return 0;
}
/*
Thanks,
Peter
*/