23

static_cast仮想ベースからダウンキャストできないのはなぜですか?

struct A {};
struct B : public virtual A {};
struct C : public virtual A {};
struct D : public B, public C {};

int main()
{
  D d;
  A& a = d;
  D* p = static_cast<D*>(&a); //error
}  

g ++ 4.5によると:

 error: cannot convert from base ‘A’ to derived type ‘D’ via virtual base ‘A’

解決策は使用することdynamic_castです?しかし、なぜ。合理的なものは何ですか?

-編集-
以下の非常に良い答え。ただし、サブオブジェクトとvtableがどのように順序付けられるかを正確に説明する回答はありません。次の記事は、gccのいくつかの良い例を示しています:
http ://www.phpcompiler.org/articles/virtualinheritance.html#Downcasting

4

2 に答える 2

11

明白な答えは次のとおりです。標準がそう言っているからです。この標準の背後にある動機は、static_cast 些細なことに近いはずです。せいぜい、ポインタへの定数の単純な加算または減算です。仮想ベースへのダウンキャストでは、より複雑なコードが必要になります。おそらく、vtableのどこかに追加のエントリがある場合でも同様です。D(さらに派生すると、相対の位置が変わる可能性があるため、定数以上のものが必要です 。)で仮想関数を呼び出し、その関数がで実装されている場合、コンパイラは次のことを行う必要があるAため、変換は明らかに実行可能です。ただし、追加のオーバーヘッドはに不適切であると見なされました。(おそらく、そのような場合に使用する唯一の理由は最適化です。A*Dstatic_caststatic_castdynamic_cast通常、推奨されるソリューションです。それで、とにかくstatic_cast同じくらい高価である可能性が高い ときdynamic_cast、なぜそれをサポートするのですか。)

于 2011-05-18T12:42:50.387 に答える
10

オブジェクトが実際にタイプE(Dから派生)である場合、Aサブオブジェクトに対するサブオブジェクトの位置はD、オブジェクトが実際にある場合とは異なる可能性があるためですD

代わりにAからCにキャストすることを検討した場合、実際にはすでに発生しています。Cを割り当てる場合、Aのインスタンスが含まれている必要があり、特定のオフセットに存在します。ただし、Dを割り当てると、CサブオブジェクトはBに付属するAのインスタンスを参照するため、オフセットが異なります。

于 2011-05-18T12:22:51.033 に答える