虚関数テーブルとダイナミックバインド

1918 ワード

虚関数テーブルとダイナミックバインド
一.単一継承ダミーテーブルモデル
•虚関数を含むクラス
class B 
 { 
    virtual int f1 (void); 
    virtual void f2 (int); 
    virtual int f3 (int); 
 };

•コンパイラは、虚関数を含むクラスごとに虚関数テーブルを生成します.すなわち、各虚関数アドレスを格納する関数ポインタ配列を虚表(vtbl)と略称し、各虚関数は虚関数テーブルのインデックス番号–0->B::f 1->B::f 2 2->B::f 3
コンパイラは、虚関数を含むクラスの虚関数テーブルを生成するほか、クラスに暗黙的なメンバー変数を追加します.通常、このクラスのインスタンス化オブジェクトの開始位置で、虚関数テーブルのヘッダアドレスを格納するために使用されます.この変数は虚関数テーブルポインタ、略称虚指針(vptr)と呼ばれます.
•コード:B*pb=new B;pb->f3 (12); pb->vptr[2](pb,12);//B::f 3呼び出しオブジェクトのアドレスはthisポインタとして、メンバー関数の最初の(見えない)パラメータに渡されます.
•ダミーテーブルは、1つのオブジェクトではなく1つのクラス1枚で、同じクラスの複数のオブジェクトは、それぞれのダミーポインタで同じダミーテーブルを共有します.
•Bから継承されたサブクラス
–class D : public B { int f1 (void); int f3 (int); virtual void f4 (void); };
•サブクラスはベースクラスのf 1とf 3を上書きし、ベースクラスのf 2を継承し、独自のf 4を追加します.コンパイラは同様にサブクラスに固有の虚表を生成します.
–0 -> D::f1 1 -> B::f2 2 -> D::f3 3 -> D::f4
•サブクラスのダミーテーブルを指すダミーポインタは、サブクラスオブジェクトのベースクラスのサブオブジェクトに格納されます.通常、開始位置にあります.
•コード:B*pb=new D;pb->f3 (12);
pb->vptr[2](pb,12);//D::f 3これがいわゆる多態です
二.ダイナミックバインドとは
•コンパイラは、ポインタまたは参照によって虚関数を呼び出す文を見た場合、関数呼び出しに関する命令の生成を急ぐのではなく、実行時に実行される文の代わりにコードを使用します.
1.呼び出しポインタまたは参照先オブジェクトの真のタイプを決定する
2.呼び出しポインタまたは参照先オブジェクトから虚関数テーブルを見つけ、虚関数テーブルから呼び出した虚関数のエントリアドレスを取得する
3.エントリアドレスに基づいて、この関数を呼び出す
三.ダイナミックバインドがパフォーマンスに与える影響
•ダミー関数テーブル自体がメモリ容量のオーバーヘッドを増加
•通常の関数呼び出しと比較して、ダミー関数呼び出しにはいくつかのステップが追加され、実行時間のオーバーヘッドが増加します.
•動的バインドは、コンパイラがインラインでコードを最適化するのを妨げる
•マルチステート特性が必要な場合のみ虚関数を使用します.そうでない場合は、できるだけ一般関数を使用します.