もとは友人に説明したときのものだがここにも置いておく。

c言語でclassを模倣するテク。downcastとかしたかったら型を保持するtagを埋め込む。こういうのを自動でかつもっと上手くやってくれるのがc++のclass。

警告は明示的にcast(視認性のため省いた)する(あるいは-Wno-incompatible-pointer-typesを添える)と消える。

#include <stdio.h>
#include <stdlib.h>

struct Super {
    void (* func)(struct Super *);
    char c;
};
void super_func(struct Super *that) {
    that->func(that);
}

struct SubA {
    struct Super super;
    int a;
};
void sub_a_func(struct Super *super) {
    struct SubA *that = super;
    for (int i = 0; i < that->a; ++i) printf("*");
    printf("\n");
}
void sub_a_init(struct Super *super) {
    struct SubA *that = super;
    that->super.func = &sub_a_func;
    that->a = 6;
    that->super.c = 'a';
}

struct SubB {
    struct Super super;
    double b;
};
void sub_b_func(struct Super *super) {
    struct SubB *that = super;
    printf("%lf %c\n", that->b, that->super.c);
}
void sub_b_init(struct Super *super, double b, char c) {
    struct SubB *that = super;
    that->super.func = &sub_b_func;
    that->b = b;
    that->super.c = c;
}

int main(void) {
    struct SubA *a = malloc(sizeof(struct SubA));
    sub_a_init(a);
    struct SubB *b = malloc(sizeof(struct SubB));
    sub_b_init(b, 3.14, 'x');

    super_func(a);
    super_func(b);

    free(a);
    free(b);
    return 0;
}