鍋あり谷あり

テーマを決めずに適当に書いています。

昨日の続き

コメントを頂いたのはいいんだが、リンク先の内容は仕事で故意にそういうことを書く人がいたら厳重に注意する必要があるような内容だと思う。
そもそも。
C++ の仮想関数の仕組みを利用せずに似たようなことをしようと思った場合、オーバーライドに当たる機能はヘッダに書く必要はない。
つまり。
昨日書いた愚痴は、仮想関数表を自分で書くならオーバーライドするかどうかなんてヘッダに書く必要はないのに、なんで C++ では書く必要があるんだこんちくしょう、というような内容のつもりであった。
で。
仮想関数表ってのを自分で書こうと思ったことがなかったので、書いてみた。
テンプレートもメンバへのポインタも仮想関数もない C++ というものを想定して。
んで。
まずは、ヘッダに書くべき内容:

struct foo{  
  int m;
  void * * vtbl;
  void hoge(){  ((void(*)(foo*))vtbl[0])(this);  }
};

struct bar : public foo{
  bar();
};

こんだけ。
キャストを書いてしまったのが悔しい。今回の趣旨に添った形でキャストを避ける方法は思いつかなかった。
vtbl[0] と書いたのは、仮想関数表の要素数が増えたら vtbl[9] とかになるよ、という気持ちの表現。

続いて cpp ファイル:

struct barimpl : public bar{
  void hogeimpl(){
    printf( "barimpl::hogeimpl, m=%d\n", m );
  }
};

void bar_hoge( barimpl * self ){
  self->hogeimpl();
}

void * bar_vtbl[] = {
  bar_hoge
};

bar::bar(){
  vtbl = bar_vtbl;
};

なんかごちゃごちゃしてしまった。
barimpl はなくてもいいんだが、こうしておくと、メンバへのアクセスで self-> といちいち書かなくてもよくなる。そのためだけのクラス。ただし、barimpl にデータメンバを追加するのは禁止。
キャストを明に書いてはいないが、実質的には foo * から barimpl * へのキャストが行われている。
その辺りがすごく気持ち悪いんだが、仮想関数呼び出しってのはそういうものなんだろう。

で。斯様にヘッダには何も書かずにオーバーライドできるわけで、やっぱり C++ はヘッダにいろんなことを書かせすぎだと思う。

思うんだが、何か見落としているような気もする。どうだろう。