(yes, that was almost literally the name of the course :-)]
I posted this to the Debian developers' mailing list, and thought I'd clean up a copy and put it here as well to share with folks.
I have to preface by saying that this does not LOOK like object-oriented programming, for those people coming from a java or C++ background. But if you think about it, it is.
Here is how an end developer would use a "FooOBJ" type object:
void diddle(){ FooOBJ fobj; fobj=newFooOBJ(); setFooNumber(fobj, 1); setFooString(fobj, "somestring"); dumpFooState(fobj); deleteFooOBJ(fobj); } int main(){ diddle(); return 0; }
"What typedef?"
See below :-)
This is BETTER object opacity than C++. Why? Because callers have **NO IDEA** what the private members really are, and how they are implemented.
FooOBJ.h consists of the following:
typedef struct fooobj * FooOBJ; FooOBJ newFooOBJ(); void setFooNumber(FooOBJ,int); void setFooString(FooOBJ,char *); /* make comments about copy or not here */ void dumpFooState(FooOBJ); /* dumps debug contents of FooOBJ to stdout */ void deleteFooOBJ(FooOBJ);
And just to spell things out and give you something to play with, here's a sample implementation of FooOBJ.o Note that there are quite a few different possibilities for it, and it doesnt matter to the "blah.c" code above. All that it needs is a FooOBJ.o file to link against.
Which is what object oriented programming is all about!
#include <stdio.h> #include "FooOBJ.h" struct fooobj { int privateint; char *privateString; /* Depending on your preferences, you * may prefer privateString to be a char buffer[], * OR malloc it and free on delete. */ }; /* Any "class static" vars simply get declared as static int staticvar; * or whatever you like here. * Whereas instance variables go in the struct above. */ FooOBJ newFooOBJ(){ FooOBJ foo=(FooOBJ)malloc(sizeof(struct fooobj)); return foo; } void setFooNumber(FooOBJ foo,int num){ if(foo==NULL) return; /* you may chose to debugprint something *instead */ foo->privateint=num; } void setFooString(FooOBJ foo,char *string){ /* If you malloced the string, you'll want to free() it here!!*/ if(foo==NULL) return; foo->privateString=string; } void dumpFooState(FooOBJ foo){ if(foo==NULL) return; printf("value of private int==%d\n", foo->privateint); printf("value of private string==%s\n", foo->privateString); } void deleteFooOBJ(FooOBJ foo){ /* dont forget to free privateString if you malloced it here!!*/ free(foo); }
cc -c *.c cc -o foo *.oThen if you want to play with the implementation of the "FooOBJ" object, you can change just the implementation part with:
cc -c FooOBJ.c cc -o foo *.o