Last active
May 22, 2021 11:31
-
-
Save ddlsmurf/6861658 to your computer and use it in GitHub Desktop.
Example for C users of how classes and virtual lookup tables can work. Proper memory and error management left out. #tutorial #oop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
basic debug on object of type 'base', data: 0xdeadbeef | |
basic debug on object of type 'pointer', data: 0xdeadbeef | |
int debug (type 'int') value: '123' | |
No method 'sayHi' in 'int' | |
string debug (type 'string') value: 'hi guys' | |
Howdidledidoo 'string' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdarg.h> | |
#include <stdio.h> | |
#include <strings.h> | |
struct class_instance; | |
typedef void (*method_pointer)(struct class_instance *self); | |
struct class_method { | |
char *name; | |
method_pointer function; | |
}; | |
struct class_definition { | |
char *name; | |
struct class_definition *inheritedClass; | |
int methodCount; | |
struct class_method **methods; | |
}; | |
struct class_instance { | |
struct class_definition *class; | |
void *instance_data; | |
}; | |
struct class_definition *newClass( | |
char *name, | |
struct class_definition *inheritedClass, ...) { | |
va_list args; | |
va_list argsCopy; | |
va_start(args, inheritedClass); | |
va_copy(argsCopy, args); | |
int methodCount = 0; | |
struct class_method *dummy; | |
struct class_method **method; | |
while (dummy = va_arg(argsCopy, struct class_method *)) | |
methodCount++; | |
va_end(argsCopy); | |
size_t size = | |
sizeof(struct class_definition) + | |
methodCount * sizeof(struct class_method *); | |
struct class_definition *result = malloc(size); | |
bzero(result, size); | |
result->name = name; | |
result->inheritedClass = inheritedClass; | |
result->methodCount = methodCount; | |
method = result->methods = (struct class_method **)(result + 1); | |
while (dummy = va_arg(args, struct class_method *)) { | |
*method = dummy; | |
method++; | |
} | |
va_end(args); | |
return result; | |
} | |
struct class_instance *newObject(struct class_definition *class, void *data) { | |
struct class_instance *object = malloc(sizeof(struct class_instance)); | |
object->class = class; | |
object->instance_data = data; | |
return object; | |
} | |
method_pointer findMethod(struct class_definition *class, char *methodName) { | |
int i = class->methodCount; | |
while (i-->0) { | |
if (strcmp(class->methods[i]->name, methodName) == 0) { | |
return class->methods[i]->function; | |
} | |
} | |
return class->inheritedClass ? findMethod(class->inheritedClass, methodName) : 0; | |
} | |
void runMethod(struct class_instance *object, char *methodName) { | |
method_pointer method = findMethod(object->class, methodName); | |
if (method) | |
method(object); | |
else | |
printf("No method '%s' in '%s'\n", methodName, object->class->name); | |
} | |
void baseClassDebug(struct class_instance *self) { | |
printf("basic debug on object of type '%s', data: %p \n", self->class->name, self->instance_data); | |
} | |
struct class_method baseClassDebugMethod = { "debug", baseClassDebug }; | |
void stringClassDebug(struct class_instance *self) { | |
printf("string debug (type '%s') value: '%s'\n", self->class->name, (char*)self->instance_data); | |
} | |
struct class_method stringClassDebugMethod = { "debug", stringClassDebug }; | |
void stringClassSayHi(struct class_instance *self) { | |
printf("Howdidledidoo '%s'\n", self->class->name, (char*)self->instance_data); | |
} | |
struct class_method stringClassSayHiMethod = { "sayHi", stringClassSayHi }; | |
void intClassDebug(struct class_instance *self) { | |
printf("int debug (type '%s') value: '%i'\n", self->class->name, (int)self->instance_data); | |
} | |
struct class_method intClassDebugMethod = { "debug", intClassDebug }; | |
int main() { | |
/* Pseudo object code: | |
class base { | |
void *data; | |
void constructor(data) { this.data = data; } | |
void debug() { ...baseClassDebug... } | |
} | |
class pointer inherits base { | |
} | |
class string inherits base { | |
void debug() { ...stringClassDebug... } | |
void sayHi() { ...stringClassSayHiMethod... } | |
} | |
class int inherits base { | |
void debug() { ...intClassDebug... } | |
} | |
*/ | |
struct class_definition *baseClass = newClass("base", 0, &baseClassDebugMethod, 0); | |
struct class_definition *pointerClass = newClass("pointer", baseClass, 0); | |
struct class_definition *stringClass = newClass("string", baseClass, &stringClassDebugMethod, &stringClassSayHiMethod, 0); | |
struct class_definition *intClass = newClass("int", baseClass, &intClassDebugMethod, 0); | |
/* objectOfBase = new base(0xdeadbeef); */ | |
struct class_instance *objectOfBase = newObject(baseClass, (void *)0xdeadbeef); | |
/* objectOfBase.debug(); */ | |
runMethod(objectOfBase, "debug"); | |
/* objectOfPointer = new pointer(0xdeadbeef); */ | |
struct class_instance *objectOfPointer = newObject(pointerClass, (void *)0xdeadbeef); | |
/* objectOfPointer.debug(); */ | |
runMethod(objectOfPointer, "debug"); | |
/* objectOfInt = new int(123); */ | |
struct class_instance *objectOfInt = newObject(intClass, (void *)123); | |
/* objectOfInt.debug(); */ | |
runMethod(objectOfInt, "debug"); | |
/* objectOfInt.sayHi(); */ | |
runMethod(objectOfInt, "sayHi"); | |
/* objectOfString = new string("hi guys"); */ | |
struct class_instance *objectOfString = newObject(stringClass, "hi guys"); | |
/* objectOfString.debug(); */ | |
runMethod(objectOfString, "debug"); | |
/* objectOfString.sayHi(); */ | |
runMethod(objectOfString, "sayHi"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment