pointers-memory · advanced · ~15 min

OOP-style vtable polymorphism in C

Implement dynamic dispatch and object-oriented polymorphism in C using vtables and self pointers.

Challenge

Object-oriented languages implement dynamic dispatch using virtual method tables (vtables). In C, object polymorphism is achieved manually by storing a pointer to a vtable struct of function pointers inside a base structure.

Your Task

Implement:

struct shape_vtable {
    int (*area)(const void *self);
    int (*perimeter)(const void *self);
};

struct shape {
    const struct shape_vtable *vptr;
};

struct rect {
    struct shape base;
    int width;
    int height;
};

void rect_init(struct rect *r, int width, int height);
int shape_area(const struct shape *s);
int shape_perimeter(const struct shape *s);

Rules

  1. Implement static functions for rect that compute:
    • area: width * height
    • perimeter: 2 * (width + height)
  2. Link these functions in a shared struct shape_vtable rect_vtable.
  3. In rect_init: set r->base.vptr = &rect_vtable, r->width = width, and r->height = height.
  4. In shape_area: dispatch s->vptr->area(s). If s == NULL or vptr == NULL, return 0.
  5. In shape_perimeter: dispatch s->vptr->perimeter(s). If s == NULL or vptr == NULL, return 0.

Input format

r: pointer to struct rect; width, height: dimensions; s: generic struct shape pointer.

Output format

Returns computed area or perimeter via vtable dispatch.

Constraints

C11 freestanding. Vtable polymorphism pattern.

Starter code

#include <stddef.h>

/* The harness provides:
struct shape_vtable {
    int (*area)(const void *self);
    int (*perimeter)(const void *self);
};
struct shape {
    const struct shape_vtable *vptr;
};
struct rect {
    struct shape base;
    int width;
    int height;
};
*/

void rect_init(struct rect *r, int width, int height) {
    (void)r; (void)width; (void)height;
}

int shape_area(const struct shape *s) {
    (void)s;
    return 0;
}

int shape_perimeter(const struct shape *s) {
    (void)s;
    return 0;
}

Common mistakes

Not casting self back to struct rect* inside the method implementations; dereferencing NULL vptr.

Edge cases to handle

NULL shape returns 0; zero width/height returns 0 area; dispatching through base shape pointer.

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.