2012-01-27 6 views
0

dynamic bindingでは、関数呼び出しは、ポインタが指しているオブジェクトの型に基づいて関数の実装にバインドされます。 基本クラスのサブオブジェクトへのポインタ。どの仮想関数のバージョンが呼び出されますか?

base *bptr = new derived; 
bptr->func(); 

が機能 funcは、基本クラスの仮想宣言されてみましょう:

は、我々は次のコードがあるとします。次に、派生クラスの仮想関数funcのバージョンは、動的バインディングのために実行時に呼び出されます。

私は上記の考え方を理解しています。

しかし、私は上記の概念を勉強した後、私が学んだ以下のコンセプトで混乱しました。

上記のコードスニペットでは、派生クラスオブジェクトへのポインタは、暗黙的にベースクラスオブジェクトへのポインタに変換されます。次にbptrは、実際には、派生クラスオブジェクトの基本クラスのサブオブジェクトを指し、派生クラスオブジェクトを指していません。

基本クラスポインタbptrが基本クラスのサブオブジェクトを指しているため、実行時に基本クラスの仮想関数のバージョンfuncを呼び出さないでください。この例では

答えて

3

動的バインディングが実際に意味するものはありません。つまり、ポインタ(静的)がベースのサブオブジェクトを参照していても、呼び出しは完全オブジェクトの(動的)タイプに送出されます。

一般的な実装は、仮想関数テーブルを使用します。ベースサブオブジェクトは、それが属する実際の完全型の仮想関数テーブルへのポインタを隠しメンバとして格納する。仮想関数へのすべての呼び出し(動的ディスパッチが無効化されていない)は、その余分なレベルの間接化を介してルーティングされ、最後のオーバーライドが呼び出されます。

コンパイラは、そのテーブルと隠れポインタがどのように管理されているかについて、仮想関数を持つ各タイプのeテーブルを作成し、異なるコンストラクタにコードを挿入してポインタを更新します。したがって、基本サブオブジェクトを構築する際には、ポインタは基本vtableを参照しますが、派生コンストラクタに入る前に、注入されたコードは派生vtableを参照するようにポインタを(ベースで)更新します。

+0

David:派生クラスオブジェクトのvptrとその基底クラスサブオブジェクトのvptrの両方が派生クラスVTABLEを指していますか? –

+0

@Linux - vptrはオブジェクトの実際の型のvtableを指します。あなたがここで問題ないオブジェクトを指すのに使うポインタ*。 –

+0

@LinuxPenseur:派生型が新しい仮想関数を宣言しないと仮定すると、派生vtableを指す基本サブオブジェクトに格納される単一のポインタが存在します。 –

0

base *bptr = new derived; 
bptr->func(); 

baseクラスは、ちょうどそれが派生オブジェクトのインスタンスを指しているように、呼び出すことができる方法を知っているインタフェースとして何らかの方法に使用されます。 vtable(http://en.wikipedia.org/wiki/Virtual_method_table)は、derivedクラスのメソッドが呼び出されるようにします。

1

これで混乱しないでください。 "派生クラスオブジェクトへのポインタは、暗黙的にベースクラスオブジェクトへのポインタに変換されます" - この文の重要性は、baseには存在しないderivedOnly()というメソッドがあるとします。今度はbptr->derivedOnly();を試してみると、実際にderivedのオブジェクトを参照しているときでさえエラーになります。

したがって、bptrは確かにbaseへのポインタです。

関連する問題