仮想関数周りの処理
abdev 7月 15th, 2006JavaやC++、C#などでは当たり前のように使ってしまう仮想関数。同じ名前のメソッドでも、そのクラスの階層、はたまた時系列によってその内容は変わっていくという不思議な存在であります。また、モジュール設計を重視する上では非常に便利で有効な手段です。
しかし、これらを言語レベルで提供していくには、結構面倒な壁にぶち当たるときがあります。仮想関数ポインタを配列で提供するvtblなど、普段は意識することがありませんが、実は裏方で地味な作業をしているのです。
コンストラクタを順次に呼び出していく仮定で、vtblの内容の決定タイミングは非常に重要になってきます。例えば、クラスA、クラスBがあったとします(クラスAはクラスBのスーパークラス、因みに仮想関数を持ちます)。
- クラスBがNewされる
- vtblをcallocし、クラスAで実装可能な関数ポインタをセット
- クラスAのコンストラクタを実行
- vtblをreallocし、クラスBで実装可能な関数ポインタをセット
- クラスBのコンストラクタを実行
これでやっとクラスBの機能を使えるようになります。まぁ、これらの処理はプログラマは概念的に知っておくだけで全く問題ありません。言語処理系が面倒を見る部分ですから・・・
しかし、その言語処理系を抱える私は、これらの手順が少しでも違っただけで、アクセス違反の大きなタネを作っていることになります。複雑で長いコードではありますが、慎重に扱っていきたいものです。
7月 15th, 2006 at 22時40分22秒
ふと思ったのですが,vtblは動的確保する必要あるのですか?同じクラスならvtblは同じになるはずですから,1クラスにつき1つをグローバルに用意したら良い様に思いますが,それでは何か問題があるのでしょうか?
7月 16th, 2006 at 23時11分11秒
確かに、言われてみれば動的に確保する必要はなく、クラス毎に一つずつvtblを用意するだけで事足りるのかもしれません。調べてみたら、C++なんかはドンピシャですね!パフォーマンスを考慮すると、問題がないようだったら静的なvtblを用意するほうが良さそうか…。とにかく、有益な情報、ありがとうございます!