問題タブ [vptr]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - C++には仮想テーブルが必要ですか?
最近、C++ の仮想テーブルについて疑問があります。
なぜ C++ は仮想テーブルを使用するのですか?
⇒C++コンパイラは実際の関数アドレスを知らないため
--->なぜですか?
=>C++ コンパイラはオブジェクトの正確な型 (Cat? Dog? Animal?) を認識していないため、ポインタ「panimal」が指している
- -どうして?コンパイラがオブジェクトの種類を把握できる方法はありますか?
=>はい、コンパイラはobject type を追跡することで作成できると思います。
オブジェクト ポインターがその値を取得するソースを考えてみましょう。確かに2ソース。
- 別のポインタ
- クラスインスタンスのアドレス 「別のポインタ」はどこでその値を取得しますか? 最終的に、「クラス インスタンス」から値を取得するポインターが存在します。
したがって、割り当てスレッドを元のソース オブジェクトまでさかのぼって追跡することにより、
=>コンパイラはポインタの正確なタイプを把握できます。
=>コンパイラは、呼び出されている正確な関数のアドレスを知っています
=>仮想テーブルは必要ありません。
オブジェクト タイプの追跡により、各クラス インスタンスの仮想テーブル メモリと仮想テーブル ポインタの両方が保存されます。
オブジェクト タイプの追跡が機能しないのはどこですか?
ライブラリのリンク。
ライブラリ関数が基本クラスのポインターを返す場合、コンパイラが元のソース オブジェクトを追跡する方法はありません。コンパイラは、おそらくライブラリ コードと非ライブラリ コードに適応できます。エクスポートされるライブラリ クラスについては、仮想テーブルを使用します。他のクラスの場合は、メモリを節約するためにオブジェクト タイプを追跡するだけです。
上記の記述に誤りがあるかどうかはわかりませんが、もしあればご指摘ください。よろしくお願いします〜
c++ - 単一の vtable が新しい仮想関数をどのように追跡しているか?
私は VS 2013 を使用しており、vptr と vftable がオブジェクト レベルでどのように機能しているかを確認しようとしています。だから私は次のクラスを持っています:
そして、これはデバッグ時に私が見るものです:
理論的には、2 つの vptr が必要です。1 つは baseClass の vftable 用で、もう 1 つは新たに追加された derivedClassOnlyVirtualFunc() を追跡するための派生クラス用です。
しかし、ご覧のとおり、vptr/vftable は 1 つしかありません。しかし、メカニズムは正常に動作します。
ウォッチウィンドウに見えない 2 番目の vptr があると思ったので、オブジェクトのサイズを出力しました。これは 4 バイトであり、ポインターが 1 つだけ存在することを示します。
では、これは新しく追加された仮想機能でどのように機能するのでしょうか?
これによれば、2 つの vptr があるはずです。
編集:Sergeが提案したように、vftableのメモリ内容を確認しましたが、実際には3つのエントリがあります。
何らかの理由で、デバッガーに表示されません。
乾杯。
c++ - C++ 子コンストラクターと VPTR
多くの情報源、書籍などでは、「子クラスのコンストラクターで this->virtualFunction を呼び出さないでください」と書かれており、一部の情報源では、それを行ってはならない理由が説明されています。構築の時点では、クラスはまったく作成されていないためです。したがって、子コンストラクターから呼び出される仮想関数は、基本クラスの関数になります。これは、子コンストラクタ本体で、そのクラスの VPTR がベース VTABLE を指していることを意味します。
だから私の質問は、
子クラスの VPTR が仮想テーブルでアドレス指定するためにオーバーライドされるオブジェクト構築の瞬間は何ですか? 自動生成されたコードの一部は、コンストラクター本体の最後またはコンストラクター本体が実行された後にそれを行うと思います。
2 番目の質問は、
なぜ VPTR が構築の最後に上書きされるのですか? 多分それにはいくつかの重要な理由がありますか?コンストラクタ本体の開始時または基本クラスの構築後に VPTR をオーバーライドできないのはなぜですか?
java - C++ および Java の仮想メカニズム
C++ と Java の仮想メカニズムに関連する混乱があります。次のプログラムの出力は異なります。私はなぜ理解できないのですか?
Java の場合:
出力は次のとおりです。
C++ では、次の出力:
は:
誰でも説明できますか?
c++ - 仮想ポインターを介してメンバー関数にアクセスするためのポインター
vptr と vtable について説明している記事を見つけました。仮想関数が格納されているクラスの場合、オブジェクトの最初のポインターはvtableへのvptrであり、vtableの配列エントリは、クラスで発生するのと同じ順序で関数へのポインターであることを知っています(テストで確認しました)プログラム)。しかし、適切な関数を呼び出すためにコンパイラがどの構文を配置する必要があるかを理解しようとしています。
例:
質問:
1.しかし、私が本当に理解しようとしているのは、コンパイラが呼び出しを ? に置き換える方法ptr->func1()
ですvptr
。通話をシミュレートする場合、どうすればよいですか? ->
演算子をオーバーロードする必要があります。しかし、実際の名前がわからないので、それでも役に立ちませんfunc1
。コンパイラが vptr を介して vtable にアクセスするとしても、のエントリがfunc1
最初の配列であり、のエントリが配列func2
の 2 番目の要素であることをどうやって知るのでしょうか? 関数の名前から配列の要素へのマッピングが必要です。
2.どうすればシミュレートできますか? コンパイラが関数を呼び出すために使用する実際の構文を提供できますfunc1
か (どのように を置き換えptr->func1()
ますか)?