だから、仮想継承でstatic_cast
を使用してダウンキャストすることは不可能ですが、どのようにそれは、次のアップキャストを行うことが可能です:オブジェクトのstatic_castを仮想継承でどのように使用できますか?
class Base {...};
class Derived : public virtual Base {...};
...
Derived *d = new Derived();
Base *b = static_cast<Base*>(d);
メモリレイアウト:
[ derived part | base part ]
私はアップキャストが考慮されていることを知っています"安全"ですが、継承が仮想の場合、コンパイル時にベースサブオブジェクトへのオフセットをコンパイラがどのように知ることができますか? static_cast
はvtable
を使用していますか?
class Third : public Derived {...};
...
Derived *d = new Third(); // non-virtual upcast, no offset will be added
Base *b = static_cast<Base*>(d);
私は同じstatic_cast
ラインを使用し、この時間は、しかし異なっているBase
サブオブジェクトへのオフセット:
我々はこのようなものを持っている場合、これは特に混乱している(それは仮想ではないことに注意してください)!オブジェクトの
メモリレイアウト:それはd
ポイントにオブジェクトの実際の動的な型に依存している場合
[ derived part | third part | base part ]
は、どのようにそれは、コンパイル時に決定することができますか?
これは通常、私が知っていることから、オフセットはvtableに保存されています。 しかし、これはコンパイル時に静的にどのように行われたのかという疑問に答えるものではありません。 私が提供した2つのケースを見ると、どのvtableに正しいオフセットがあるのかという疑問が生じますか?コンパイラは、DerivedのvtableまたはThird's vtableのどちらを参照する必要がありますか? 明らかに、vtableの2つのオフセットは異なり、正しいvtableの選択は、実行時のタイプに依存します。 これは静的な仕組みを理解できない理由です。 –
static_castの "static"は、コンパイル時に行われたことを意味しません!これは、コンパイラがコンパイル時に情報をどこで見つけるかを静的に把握できることを意味します。例えば、vtable内のオフセットを参照する場所や、ベースへの埋め込みポインタがどこにあるかを知っています(仮想継承実装されています)。 'dynamic_cast'のようにvtableのクラスのマッチを探しません。 –
static_castにはダイナミックな側面があると言っています。 そのロジックによって、なぜstatic_castは仮想継承でダウンキャストできないのですか? –