問題タブ [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.

0 投票する
3 に答える
814 参照

c++ - 仮想関数が関与していない場合でも、仮想継承に vtable が必要なのはなぜですか?

私はこの質問を読みました: C++ Virtual class inheritance object size issue、なぜ仮想継承がクラスに追加の vtable ポインターをもたらすのか疑問に思っていました。

ここで記事を見つけました: https://en.wikipedia.org/wiki/Virtual_inheritance

これは次のことを示しています。

ただし、このオフセットは通常、実行時にしかわかりません...

ここでランタイムに関連するものはわかりません。完全なクラス継承階層は、コンパイル時にすでにわかっています。仮想関数と基本ポインターの使用法は理解していますが、仮想継承にはそのようなものはありません。

一部のコンパイラ (Clang/GCC) が vtable を使用して仮想継承を実装する理由と、これが実行時にどのように使用されるかを誰かが説明できますか?

ところで、私はこの質問も見ました: vtable in case of virtual inheritanceですが、それは仮想関数に関連する回答のみを指しています。これは私の質問ではありません。

0 投票する
0 に答える
64 参照

c++ - 仮想および非仮想基本クラスの特定の配置を強制する

次のようなコードがある場合:

C のインスタンスを作成すると、そのメモリ レイアウトは次のようになります。

しかし、私が実際に欲しいのは次のようなものです:

継承順序を強制する何らかのキーワードはありますか?

コンパイルにVC++ 15を使用していますが、問題は、すべてのクラスにvoid *ポインターを使用してvtableを「偽造」する大きな自動生成コードベースを使用していることです...今、そのコードベースを使用して継承します。インスタンスは、ロードする別のフレームワークで正しく動作するために、メモリ レイアウトの特別な順序が必要になりました。そして、そのフレームワークには、先頭に A データが必要です。

0 投票する
2 に答える
741 参照

c++ - 派生クラスは、仮想テーブルへのポインターを複数持つことができますか?

CppCon2019 の BackToBasics トーク: Virtual Dispatch and Its Alternatives を見ています。発表者は、派生クラスが基本クラスから vtable ポインターを継承し、さらに独自の vptr を持っていることをスライドに示します (誤解していないと仮定します)。

もちろん、技術的にはこれは標準で義務付けられているわけではありませんが、私は少し混乱しており、 sizeof() を使用した実験でも、ポインターが 1 つだけあればよいことが示されているようです。複数の vptrs が必要な状況があるかどうかを明確にしてください。

ありがとう

PS 明確にするために、このコンテキストでは、仮想または多重継承ではなく、より一般的なパブリック継承を検討しています (プレゼンターは、トークの前半でこれについて明示的に言及しています)。

0 投票する
1 に答える
77 参照

c++ - 仮想関数宣言で別の戻り値の型を使用すると、再定義ではなくエラーがスローされるのはなぜですか?

基本クラス:

派生クラス:

上記のコードは、「戻り値の型が同一ではありません/共変エラー」をスローします。

私はそれに関するいくつかの議論を読みました。これは似ていますが、戻り値の型が同一/共変でない場合にコードが壊れるとだけ言っています。 戻り値の型が異なるメンバー関数をオーバーライドする

期待した動作が起こらないのはなぜですか?

予想される動作: Derived の VPTR は Base::f() を指します (仮想関数にオーバーライドが提供されていない場合に備えて読みました。Derived オブジェクトは継承されたクラス バージョンを使用するだけです)。また、名前 f() を非表示にするため、次のような呼び出しになります。

Derived::f() と次のような呼び出しを呼び出す必要がありました。

Base::f() 関数を呼び出すべきでした。これはコードを壊しているようには見えません。アップキャストされた場合でも、両方のクラスの VPTR が同じ Base::f() を指しているため、コードを壊すべきではありません。

私が考えることができる唯一の理由は、そのような宣言 (同じ署名と共変/同一の戻り値の型) が仮想メソッドをオーバーライドするために予約されており、それを使用して期待どおりの動作を引き起こすことができないということです。