2013-07-28 7 views
5

だから、仮想継承で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_castvtableを使用していますか?

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 ] 

は、どのようにそれは、コンパイル時に決定することができますか?

答えて

3

あなたはあなたのケースでDerivedへのポインタを持っている場合は、使用されるべきであり、あなたも暗黙的にBaseへのポインタにDerivedへのポインタを変換できるBase明らかです!任意のアドレス調整が必要な場合、コンパイラは、組み込みポインタ、vtableなどを使用してコンパイラを実行する方法を見つけ出します。正確なアプローチはC++標準で規定されていません。正確に行われることは、ABIに依存します。たとえば、Itanium C++ ABIの場合、仮想ベースのオフセットは仮想テーブルに格納されているようです。

+0

これは通常、私が知っていることから、オフセットはvtableに保存されています。 しかし、これはコンパイル時に静的にどのように行われたのかという疑問に答えるものではありません。 私が提供した2つのケースを見ると、どのvtableに正しいオフセットがあるのか​​という疑問が生じますか?コンパイラは、DerivedのvtableまたはThird's vtableのどちらを参照する必要がありますか? 明らかに、vtableの2つのオフセットは異なり、正しいvtableの選択は、実行時のタイプに依存します。 これは静的な仕組みを理解できない理由です。 –

+0

static_castの "static"は、コンパイル時に行われたことを意味しません!これは、コンパイラがコンパイル時に情報をどこで見つけるかを静的に把握できることを意味します。例えば、vtable内のオフセットを参照する場所や、ベースへの埋め込みポインタがどこにあるかを知っています(仮想継承実装されています)。 'dynamic_cast'のようにvtableのクラスのマッチを探しません。 –

+0

static_castにはダイナミックな側面があると言っています。 そのロジックによって、なぜstatic_castは仮想継承でダウンキャストできないのですか? –

関連する問題