c / expert
Snippet
Typ-markierte strukturelle Vererbung und Laufzeit-Dispatch
Die Simulation von Einfachvererbung in C erfordert das Platzieren einer gemeinsamen Basisstruktur als erstes Element jedes abgeleiteten Typs. Da C die Zeigerausrichtung bei Offset Null garantiert, können abgeleitete Zeiger sicher in BaseValue-Zeiger umgewandelt werden.
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
30
31
32
33
34
35
36
37
#include <stdio.h>typedef enum { TYPE_INT, TYPE_FLOAT } ValueType;typedef struct {ValueType type;} BaseValue;typedef struct {BaseValue base;int data;}IntValue;typedef struct {BaseValue base;float data;} FloatValue;void print_value(const BaseValue* val) {switch (val->type) {case TYPE_INT:printf("Integer: %d\n", ((const IntValue*)val)->data);break;case TYPE_FLOAT:printf("Float: %.2f\n", ((const FloatValue*)val)->data);break;}}int main(void) {IntValue iv = { .base = { .type = TYPE_INT }, .data = 42 };FloatValue fv = { .base = { .type = TYPE_FLOAT }, .data = 3.14f };print_value((const BaseValue*)&iv);print_value((const BaseValue*)&fv);return 0;}
Erklärung
1
typedef struct { BaseValue base; int data; } IntValue;
Plaziert BaseValue als erstes Strukturelement, um die Kompatibilität für Downcasting zu gewährleisten.
2
switch (val->type)
Prüft das Diskriminator-Tag im gemeinsamen Basis-Objekt-Header zur Ausführung typspezifischer Logik.
3
((const IntValue*)val)->data
Führt ein sicheres Downcasting des Basiszeigers auf den abgeleiteten Objekttyp durch.
4
print_value((const BaseValue*)&iv);
Übergibt die Adresse der abgeleiteten Struktur implizit auf den Basistyp-Schnittstellenzeiger angepasst.