JavaやC++、C#などでは当たり前のように使ってしまう仮想関数。同じ名前のメソッドでも、そのクラスの階層、はたまた時系列によってその内容は変わっていくという不思議な存在であります。また、モジュール設計を重視する上では非常に便利で有効な手段です。

しかし、これらを言語レベルで提供していくには、結構面倒な壁にぶち当たるときがあります。仮想関数ポインタを配列で提供するvtblなど、普段は意識することがありませんが、実は裏方で地味な作業をしているのです。

コンストラクタを順次に呼び出していく仮定で、vtblの内容の決定タイミングは非常に重要になってきます。例えば、クラスA、クラスBがあったとします(クラスAはクラスBのスーパークラス、因みに仮想関数を持ちます)。

  1. クラスBがNewされる
  2. vtblをcallocし、クラスAで実装可能な関数ポインタをセット
  3. クラスAのコンストラクタを実行
  4. vtblをreallocし、クラスBで実装可能な関数ポインタをセット
  5. クラスBのコンストラクタを実行

これでやっとクラスBの機能を使えるようになります。まぁ、これらの処理はプログラマは概念的に知っておくだけで全く問題ありません。言語処理系が面倒を見る部分ですから・・・

しかし、その言語処理系を抱える私は、これらの手順が少しでも違っただけで、アクセス違反の大きなタネを作っていることになります。複雑で長いコードではありますが、慎重に扱っていきたいものです。