-2

最近、C++ の仮想テーブルについて疑問があります。

なぜ C++ は仮想テーブルを使用するのですか?

⇒C++コンパイラは実際の関数アドレスを知らないため

--->なぜですか?

=>C++ コンパイラはオブジェクトの正確な型 (Cat? Dog? Animal?) を認識していないため、ポインタ「panimal」が指している

- -どうして?コンパイラがオブジェクトの種類を把握できる方法はありますか?

=>はい、コンパイラはobject type を追跡することで作成できると思います。

オブジェクト ポインターがその値を取得するソースを考えてみましょう。確かに2ソース。

  1. 別のポインタ
  2. クラスインスタンスのアドレス 「別のポインタ」はどこでその値を取得しますか? 最終的に、「クラス インスタンス」から値を取得するポインターが存在します。

したがって、割り当てスレッドを元のソース オブジェクトまでさかのぼって追跡することにより、

  =>コンパイラはポインタの正確なタイプを把握できます。

  =>コンパイラは、呼び出されている正確な関数のアドレスを知っています

  =>仮想テーブルは必要ありません。

オブジェクト タイプの追跡により、各クラス インスタンスの仮想テーブル メモリと仮想テーブル ポインタの両方が保存されます。

オブジェクト タイプの追跡が機能しないのはどこですか?

ライブラリのリンク。

ライブラリ関数が基本クラスのポインターを返す場合、コンパイラが元のソース オブジェクトを追跡する方法はありません。コンパイラは、おそらくライブラリ コードと非ライブラリ コードに適応できます。エクスポートされるライブラリ クラスについては、仮想テーブルを使用します。他のクラスの場合は、メモリを節約するためにオブジェクト タイプを追跡するだけです。

上記の記述に誤りがあるかどうかはわかりませんが、もしあればご指摘ください。よろしくお願いします〜

4

3 に答える 3

1

場合によっては、はい、コンパイル時にポインターが指す型をコンパイラーが把握できます。ただし、それができない場合を構築するのは非常に簡単です。

int x;
cin >> x;
Animal* p;
if (x == 10)
    p = new Cat();
else
    p = new Dog();

どのような場合でも、コンパイラがオブジェクトの型を証明できる場合、as-if ルールに従って、生成されたコードから仮想テーブルを自由に削除できます。

于 2014-11-20T07:57:11.423 に答える
0

コンパイラは、ポインタの正確な型を把握できます。

はい、しかし、実行時に適切な関数をどのように呼び出す必要がありますか? コンパイラは知っていますが、c++ には、実行時に渡されるオブジェクトの型を伝える仮想マシンがありません。したがって、継承された型の仮想関数の vtable が必要です。コンパイラは、各仮想関数の実行につながるすべての異なるコード パスのコードを作成し、実行時に適切な関数を呼び出しますか? 可能であれば、それははるかに大きなバイナリにつながります。

于 2014-11-20T07:50:01.323 に答える