Created
September 2, 2015 16:32
-
-
Save JonathonReinhart/643e463d754eb7bedb2c to your computer and use it in GitHub Desktop.
Object-oriented programming in C (without casts)
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 <stdio.h> | |
#include <stdlib.h> | |
#include <stddef.h> | |
void *malloc_safe(size_t n) | |
{ | |
void *p = malloc(n); | |
if (!p) { | |
fprintf(stderr, "malloc(%zd) failed\n", n); | |
abort(); | |
} | |
return p; | |
} | |
struct type_a { | |
int a; | |
}; | |
struct type_b { | |
int b; | |
}; | |
enum typeid { | |
TYPE_A, | |
TYPE_B, | |
}; | |
struct virt { | |
enum typeid typeid; | |
union { | |
char _mark[0]; | |
struct type_a a; | |
struct type_b b; | |
}; | |
/* Don't add anything after this union */ | |
}; | |
#define virt_sizeof(type) \ | |
(offsetof(struct virt, _mark) + sizeof(type)) | |
struct virt *new_a(int a) | |
{ | |
struct virt *o = malloc_safe( virt_sizeof(struct type_a) ); | |
o->typeid = TYPE_A; | |
o->a.a = a; | |
return o; | |
} | |
struct virt *new_b(int b) | |
{ | |
struct virt *o = malloc_safe( virt_sizeof(struct type_b) ); | |
o->typeid = TYPE_B; | |
o->b.b = b; | |
return o; | |
} | |
static void handle_a(struct type_a *o) | |
{ | |
printf("%s a=%d\n", __FUNCTION__, o->a); | |
} | |
static void handle_b(struct type_b *o) | |
{ | |
printf("%s b=%d\n", __FUNCTION__, o->b); | |
} | |
void handle_virt(struct virt *o) | |
{ | |
switch (o->typeid) { | |
case TYPE_A: return handle_a(&o->a); | |
case TYPE_B: return handle_b(&o->b); | |
default: | |
fprintf(stderr, "Invalid type %d\n", o->typeid); | |
abort(); | |
} | |
} | |
int main(void) | |
{ | |
struct virt *o; | |
o = new_a(33); | |
handle_virt(o); | |
free(o); | |
o = new_b(66); | |
handle_virt(o); | |
free(o); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment