C++の仮想関数の欠点
話が少し前後しますが、Part4の記事でC++の仮想関数呼び出しの仕組みについて説明しましが、ここではC++の仮想関数の欠点について指摘します。C++ではvtableというメンバ関数のアドレスを集めたテーブルを用いて仮想関数の呼び出しを実現していました。この方式は効率がよいのですが『コンパイル時に呼び出すべき仮想関数が決定しなければならない』という弱点があります。どういうことかといいますとC++でのメンバ関数呼び出し
object.virtual_method( arg1, arg2, arg3)
という呼び出しで、virtual_methodというメンバ関数名はコンパイル時に参照されますが、実行時には内部的に振られた番号(vtableのインデックス)になります。つまり実行時にはこの名前は参照できません。と同時にvtableのインデックスを取得する手段もないので、実行時に呼び出すメンバ関数を選択したいということができません。
これの何が欠点かピンとこないかもしれませんが、例えば、バッチファイルからVBScriptを使ってExcelを操ったりしますが、この特にExcelのバージョンをあまり気にせずにExcelを操作(メソッドを呼び出す)するでしょう。これと同じことは、C++の仮想関数の仕組みではストレートに実装できないということです。Windowsでは皆さんご存知のとおり、COMという仕組みをOSに実装することで実行時に呼び出すメソッドを特定することを行っています。
COMというとえらく古いと思われるかもしれませんが、.NET Framkework からExcelを呼び出す場合もCOM相互運用性という仕組みを使って.NET Framework → COM → Excel という風に呼び出しいます。
話が脱線しますが、私は.NET Frameworkが廃れるのではないか? と思っていますが、その理由のひとつが .NET FrameworkがCOMやOLE DB等のようにWindows APIを充分に置き換えていないと思えるところにあります(もっとも先のことは解りませんのでなんともいえませんが)。
関数の動的なロード&実行の例
場合によって呼び出す関数を変えるというプログラミングテクニックは、オブジェクト指向プログラミング以外にもあります。典型的な例のひとつにデバイスドライバがあります。
デバイスドライバはご存知のとおりハードウェアとOSのAPIを橋渡しするソフトウェアでハードウェアに合わせて作成されています。ハードウェアを変えるとそれにあわせてデバイスドライバも変えます。
デバイスドライバはCで記述されることが多いです。最近のOSではPlag&Playが一般的になりましたし、USB接続機器ではOSを再起動せずに、デバイスドライバがロードされます。このような動的なソフトウェアのロードの仕組みはどうなっているのでしょうか?
続いては、公開1周年記念特集記事として『プログラミング言語の制御構造のいろいろ(5)』を書いてみます。