c / expert
Snippet
Objektorientierte Polymorphie über Virtuelle Tabellen (Vtable) Funktionszeiger
Dieses Beispiel veranschaulicht, wie objektorientierte dynamische Aufrufverteilung (Dynamic Dispatch) in reinem C mittels virtueller Methodentabellen (Vtables) manuell umgesetzt wird. Durch Platzieren eines Zeigers auf eine Methodenstruktur in einer Basisstruktur können abgeleitete Strukturen Implementierungen durch Zeiger-Casting überschreiben.
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
28
29
#include <stdio.h>struct Shape;typedef struct {double (*area)(const struct Shape* self);} ShapeVTable;typedef struct Shape {const ShapeVTable* vptr;} Shape;typedef struct {Shape base;double width;double height;} Rectangle;static double rect_area(const Shape* self) {const Rectangle* rect = (const Rectangle*)self;return rect->width * rect->height;}static const ShapeVTable RECT_VTABLE = { .area = rect_area };void rect_init(Rectangle* rect, double w, double h) {rect->base.vptr = &RECT_VTABLE;rect->width = w;rect->height = h;}
Erklärung
1
double (*area)(const struct Shape* self);
Definiert ein Funktionszeiger-Mitglied in der Vtable-Struktur als virtuellen Funktionsprototypen.
2
const ShapeVTable* vptr;
Bettet einen expliziten virtuellen Tabellenzeiger in die Basis-Shape-Struktur für die Laufzeitverteilung ein.
3
Shape base;
Bettet die Basis-Struktur als erstes Element in Rectangle ein, um die Speicherlayout-Kompatibilität für Zeiger-Casting zu gewährleisten.
4
const Rectangle* rect = (const Rectangle*)self;
Führt ein sicheres Downcasting vom Basis-Shape-Zeiger zurück auf den abgeleiteten Rectangle-Typ durch.
5
rect->base.vptr = &RECT_VTABLE;
Bindet die statische Vtable-Instanz mit der konkreten Implementierung während der Strukturinitialisierung.