2

私は困惑するcスタイルのキャストがあるコードを見ています。

私はキャスティングにはかなり精通していますが、これは本当に理解できません。つまり、ここにあります: Base と Derived という 2 つのクラスがありますが、Derived はメソッド/属性を追加しません。基本的に、Base の属性の 1 つ (M_blockSize と呼びます) が 1 に固定されている場合は、Base の特定のケースにすぎません。ただし、特定の実装を必要とするメソッドはなく、機能の拡張もありません。そのような派生クラスの利点は、このスレッドのポイントではありません。開発者にはこれに正当な理由があると仮定しましょう。

とにかく、私が探しているコードでは、次のようなことが起こります。

void foo(const Derived& d){...}
[...]
Base b;
foo((Derived&) b);

そのため、開発者はベース オブジェクトを派生オブジェクトへの参照にキャストしました。私の理解では、「castee」(b) の具体的な型が実際に Derived である場合、ダウンキャストが行われます。ここではそうではありません。

ただし、これは c スタイルのキャストであるため、コンパイラは多数のキャストを試行しており、最終的にどのキャストが機能するかはわかりません。

だから、質問:

  • 1) コンパイラはどのようなキャストを行っていますか? 私はおそらく reinterpret_cast を想定していますか?
  • 2) static_cast< Derived& >(b) も同様に機能しますか?
  • 3) クラス Derived がいくつかのメソッド/属性 (foo で使用されていない) を追加した場合、これはまだ機能しますか?
  • 4) foo は、まだ Base にない Derived の機能を使用しないという重要なポイントはありますか?

質問が明確であることを願っています。ご協力ありがとうございました。

4

1 に答える 1

1

ここで有効なキャストはstatic_cast<Derived&>、次の規則 (§5.2.9 静的キャスト) によって管理される です。

型「cv1 B」の左辺値 (Bはクラス型) は型「参照への cv2 」にキャストできますD。ここで、Dは から派生したクラス (第 10 節)Bです。DB" が存在し (4.10)、cv2は cv1 と同じ cv-qualification、またはcv1より大きい cv-qualification であり、Bの仮想基底クラスでDも の仮想基底クラスの基底クラスでもありませんD。結果の型は「cv2 D 」です。

D"pointer to " から "pointer to " へのキャストBは、有効な標準変換です (§4.10):

タイプ「cv Dへのポインター」の prvalue ( はクラス タイプ) は、タイプ「 cvDへのポインター」の prvalue に変換できます。ここで、は の基本クラス (条項 10) です。 BBD

ただし、キャストが機能するからといって、それでよいというわけではありません。注 (§5.2.9):

タイプ「cv1 B」のオブジェクトが実際にタイプのオブジェクトのサブオブジェクトである場合D、結果はタイプの外側のオブジェクトを参照しますD。それ以外の場合、キャストの結果は未定義です。

したがって、このコードは未定義の動作を引き起こします。基本クラスからその派生クラスのいずれかにキャストできますが、それが本当にその派生型のオブジェクトである場合にのみ動作を定義できます。

質問に答えるには:

  1. それはstatic_cast<Derived&>です。
  2. はい、それが起こっているからです。
  3. 未定義の動作になるため、とにかく機能しません。
  4. ここで何がポイントだったのか定かではありません。内部で特定の機能を使用しなければ、期待どおりに動作し続ける可能性があると思います。ただし、その場合は、.DerivedfooBase&
于 2013-03-20T16:56:14.017 に答える