仮想関数テーブル
下記のクラスの宣言は C++ の文法に従うものとする:
これらは下記のクラスを派生させる。
GNUコンパイラコレクション の g++ 3.4.6 は、オブジェクト b2 に対して下記の 32bit メモリレイアウトを生成する。
オブジェクト d のメモリレイアウト:
仮想でない関数(f0)は通常 vtable に現れないが、いくつかの例外もある(デフォルトコンストラクタなど)。
クラス D でメソッド f2() をオーバーライドしているが、これは B2の仮想関数テーブルを複製し、B2::f2() へのポインタを D::f2() へのポインタで置き換えることで実現されている。
単なるコンパイルされたポインタへのジャンプである非仮想関数の呼び出しに対して、仮想関数の呼び出しは最低一度以上、余分にポインタをたどる操作や"fixup" が必要である。そのため、仮想関数の呼び出しは原理的に非仮想の関数呼び出しに対して低速である。実験によれば 6-13% の実行時間が単なる関数のディスパッチに用いられ、オーバーヘッドは場合によって 50% に達する。
さらに、 JIT コンパイルが使用できない環境では、仮想関数は通常インライン展開できない。テーブルの参照を行う部分を、たとえばインライン化された本体部分を条件文で実行させることも可能ではあるが、そうした最適化は一般的ではない。
オーバーヘッドを避けるため、コンパイラはコンパイル時に呼び出しが解決できる場合には vtable の生成を行わない。
従って、上記の f1 の呼び出しは、 d が現時点で D のみ保持しており、D が f1 をオーバーライドしないことをコンパイラが判断できるため、vtable の検索は必要なくなる可能性がある。コンパイラ(あるいは最適化プログラム)はプログラム内に f1 をオーバーライドする B1 のサブクラスがないことを検出することができるかもしれない。実装が明示的に指定されているため(this ポインタの fixup が必要ではあるが)B1::f1 または B2::f2 はおそらく vtable の検索を必要とすることはない。