c / expert
Snippet
Dynamic Interface Dispatch using Virtual Method Tables
Object-oriented dynamic dispatch can be cleanly implemented in standard C by nesting a base structure containing a pointer to a virtual method table (VTable). Sub-structures place the base struct as their first member, ensuring memory alignment allows safe pointer casting from the base type to derived types and enabling runtime polymorphism.
snippet.c
c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>struct Shape;typedef struct {double (*area)(const struct Shape *self);} ShapeVTable;typedef struct Shape {const ShapeVTable *vtable;} Shape;typedef struct {Shape base;double radius;} Circle;static double circle_area(const Shape *self) {const Circle *c = (const Circle *)self;return 3.1415926535 * c->radius * c->radius;}static const ShapeVTable circle_vtable = { .area = circle_area };void circle_init(Circle *c, double r) {c->base.vtable = &circle_vtable;c->radius = r;}
Breakdown
1
typedef struct { double (*area)(const struct Shape *self); } ShapeVTable;
Defines the vtable containing function pointers for polymorphic operations.
2
typedef struct Shape { const ShapeVTable *vtable; } Shape;
Base class equivalent holding an immutable pointer to its runtime method table.
3
typedef struct { Shape base; double radius; } Circle;
Derived struct placing Shape base as its first member to guarantee identical initial memory offset.
4
const Circle *c = (const Circle *)self;
Safely downcasts the base pointer to the derived type based on standard C layout guarantees.
5
static const ShapeVTable circle_vtable = { .area = circle_area };
Instantiates a shared, read-only vtable instance bound specifically to Circle implementations.