5.2.7(ISO / IEC 14882、2003年12月29日)は、この点でかなり明確です。
【表現についてdynamic_cast<T>(v)
】
T
が「pointertocv1 」であり、タイプが「pointer to cv2 」 であり、の基本クラスである場合、結果は、が指すオブジェクトの一意のサブオブジェクトへのポインタになります。[... bla bla about cv1 and cv2 ...]そしてBは、アクセス可能な明確なDの基本クラスでなければなりません(私の強調)B
v
D
B
D
B
D
v
(11.2 「基本クラスの発明されたパブリックメンバーがアクセス可能である場合、基本クラスはアクセス可能であると言われます。」を思い出してください。 )
これは、最初のキャストが機能する理由を説明しています。さて、2番目に:
[...]
それ以外の場合は、実行時チェックが適用され、によってポイントまたは参照されるオブジェクトが、によってv
ポイントまたは参照されるタイプに変換できるかどうかが確認されT
ます。
実行時チェックは、論理的に次のように実行されます。
- が指す(参照する)最も派生したオブジェクトで、オブジェクトの基本クラスのサブオブジェクトを
v
指すv
(参照する)場合、およびが指す(参照する)サブオブジェクトからT型のオブジェクトが1つだけ派生する場合、結果は、その
オブジェクトへのポインタ(参照する左辺値)です。public
T
v
T
- それ以外の場合、最も派生したオブジェクトの基本クラスサブオブジェクトを
v
指す(参照する)場合public
、最も派生するオブジェクトのタイプにT
、明確なタイプの基本クラスがありpublic
、結果はポインター(参照する左辺値)になります。 )T
最も派生したオブジェクトのサブオブジェクトに。
- それ以外の場合、実行時チェックは失敗します。
失敗したポインター型へのキャストの値は、必要な結果型のnullポインター値です。参照型へのキャストが失敗すると、bad_cast(18.5.2)がスローされます。
したがって、観察する動作はprivate
継承によるもののようです。基本クラスがアクセス可能であっても、パブリックではなく、標準ではパブリックが必要であり、アクセスできません。
迷惑ですね。私はC++0xドラフトを手元に持っていません。状況が変わった場合に備えて、誰かが私の答えを引用符で編集できるかもしれません。
このキャストを達成する別の方法はありますか?
それはあなたが何をしたいかによります。基本的に、プライベート継承は、構成を実行するための単なる別のデバイスです。本当にプライベート派生インスタンスへのポインタを返す場合は、継承をパブリックにするか、メンバーを返します。
とにかく、あなたはそれstatic_cast
がこの制限を持っていないように見えることを知って幸せになるでしょう:
5.2.9。[約static_cast<T>(v)
][...]
タイプ「pointertocv1B」(Bはクラスタイプ)の右辺値は、タイプ「pointer to cv2 D」の右辺値に変換できます。ここで、Dは、有効な標準の場合、 Bから派生したクラス(10節)です。 「ポインターからD」から「ポインターからB」への変換が存在し(4.10)、cv2はcv1と同じかそれ以上のcv資格であり、BはDの仮想基本クラスではありません。nullポインター値(4.10)は、宛先タイプのnullポインター値に変換されます。タイプ「pointertocv1B」の右辺値が、実際にはタイプDのオブジェクトのサブオブジェクトであるBを指している場合、結果のポインターはタイプDの囲んでいるオブジェクトを指します。それ以外の場合、キャストの結果は未定義です。 。
したがって、ポインタの実際の動的タイプが何であるかを確実に知っている場合は、static_cast
内部に入ることができますfoo
。
この不整合が存在する理由についての追加情報に興味があります。