Ognacさんが何か違うぞで書かれていたことをCで書いてみました。
# 元ネタはアセンブラって話ですが
この手のことは既に手垢が付きまくっていてまぁ今更感もあるのですが。
# その癖に無駄に長いコード載せてスイマセン
#include <stdio.h>
typedef struct c_a_tag c_a; // 自オブジェクトの型が必要なので先にtypedef
typedef struct { // 仮想関数テーブル
void (*func)(c_a* self);
} c_a_if;
struct c_a_tag {
const c_a_if* i_f;
int a;
};
typedef struct c_b_tag c_b;
struct c_b_tag { // c_aを継承したつもりのc_b
c_a super;
int b;
};
typedef struct c_c_tag c_c;
struct c_c_tag { // c_aを継承したつもりのc_b
c_a super;
int c;
};
void c_a_func(c_a* self) // 気分的には c_a::funcな仮想関数
{
printf("Class c_a: a=%d\n", self->a );
}
void c_b_func(c_a* self) // 気分的には c_b::funcな仮想関数
{
c_b* self_b = (c_b*) self;
printf("Class c_b: a=%d/b=%d\n", self_b->super.a, self_b->b);
}
void c_c_func(c_a* self) // 気分的には c_c::funcな仮想関数
{
c_c* self_c = (c_c*) self;
printf("Class c_c: a=%d/c=%d\n", self_c->super.a, self_c->c);
}
// 仮想関数テーブル
const c_a_if c_a_if_i = { c_a_func };
const c_a_if c_b_if_i = { c_b_func };
const c_a_if c_c_if_i = { c_c_func };
// 各クラスのコンストラクタ的なもの
void construct_c_a(c_a* obj)
{
obj->i_f = &c_a_if_i;
obj->a = 0;
}
void construct_c_b(c_b* obj)
{
construct_c_a(&obj->super);
obj->super.i_f = &c_b_if_i;
obj->super.a = 1;
obj->b = 10;
}
void construct_c_c(c_c* obj)
{
construct_c_a(&obj->super);
obj->super.i_f = &c_c_if_i;
obj->super.a = 2;
obj->c = 20;
}
// お試しメイン
int main(void)
{
c_a a;
c_b b;
c_c c;
c_a* ar[3];
int i;
construct_c_a(&a);
construct_c_b(&b);
construct_c_c(&c);
ar[0] = &a;
ar[1] = (c_a*) &b;
ar[2] = (c_a*) &c;
for(i = 0; i < 3; i++) ar[i]->i_f->func(ar[i]);
return 0;
}
------実行結果------
Class c_a: a=0
Class c_b: a=1/b=10
Class c_c: a=2/c=20
------------------------
多分上司の方が言いたかったことはこういう事なんでしょう。
アセンブラで書く場合、構造体はオフセットで表すことが出来るので、各構造体のメンバの取得は
mov eax,ofs[ebx] (x86だとこんな書き方だったっけ?)
みたいな感じで出来ますね。
main関数のforループのところまで来ると便利な感じで使えますが、そこまでのセットアップが面倒くさい。
とは言え僕はCオンリーな開発の場合この手の事をけっこうやっちゃいます。
多態モドキが出来ることが結構便利なのよね。