9

レイモンド・チェンのブログ投稿の返信で

質問者が指摘した

レイモンド、派生クラスの基本クラスサブオブジェクトの位置はISO C ++ 2003標準(10-3、168ページ)に従って指定されていないため、C ++の例は正しくないと思います。また、基本クラスサブオブジェクトは常に次の場所にあると想定します。始まり。Cの例はC++でも問題ないので、私はそれに固執します。

レイモンドは答えた

[コードはこの仮定をしていません。そのため、reinterpret_castではなくstatic_castを使用することが重要です。試してみてください:OVERLAPPEDに仮想メソッドを追加して(vtableが前面に表示されるように)、コンパイラーの動作を観察します。-レイモンド]

彼のコメントを読んだ後、私は推測することができました。この例ではstatic_castを使用しても問題ありませんが、reinterpret_castは問題ありません。reinterpret_castはvtableを変換しないためです。私はそれを正しく理解していますか?
しかし、そこで(reinterpret_castではなく)Cスタイルのキャストを使用すると、それもうまくいかない可能性がありますか?

それを理解するために、より効果的なC++のキャストの説明を読み直しました。しかし、それについての答えはありませんでした。

4

1 に答える 1

17

この例ではstatic_castを使用しても問題ありませんが、reinterpret_castは問題ありません。reinterpret_castはvtableを変換しないためです。

いいえ、問題は、reinterpret_castが継承について完全に気づいていないことです。同じアドレスを変更せずに返すだけです1。ただし、ダウンキャストを実行していることはstatic_cast わかっています。つまり、基本クラスから派生クラスにキャストしています。関係する両方のタイプを知っているので、それに応じてアドレスを調整します。つまり、正しいことを行います。

私たちの実装OVERLAPPEDEXが次のような仮想関数を持つ架空のクラスをレイアウトしているとしましょう。

+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
       ^
       |
      ptr

OVERLAPPED与えられたポインタはサブオブジェクトを指しています。reinterpret_castそれを変えることはありません。タイプを変更するだけです。明らかに、OVERLAPPEDEXこのアドレスを介してクラスにアクセスすると、サブオブジェクトの場所がすべて間違っているため、簡単に大混乱を引き起こします。

       what we believe we have when we access OVERLAPPEDEX through the pointer
       +------+------------+------------------+-------------+
       | vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------+-----+------+-----------+------+------+------+
| vptr | OVERLAPPED | AssociatedClient | ClientState | <- what we actually have
+------+------------+------------------+-------------+
       ^
       |
      ptr

static_cast に変換するOVERLAPPED*にはアドレスを調整する必要があることを知っOVERLAPPEDEX*ており、正しいことを行います。

 +------+------------+------------------+-------------+
 | vptr | OVERLAPPED | AssociatedClient | ClientState |
 +------+------------+------------------+-------------+
 ^
 |
ptr after static_cast

しかし、そこで(reinterpret_castではなく)Cスタイルのキャストを使用すると、それもうまくいかない可能性がありますか?

Cスタイルのキャストは、成功する次の最初のキャストとして定義されます。

  1. const_cast
  2. static_cast
  3. static_cast、 それからconst_cast
  4. reinterpret_cast
  5. reinterpret_cast、 それからconst_cast

ご覧のとおり、astatic_castは前に試さreinterpret_castれているので、この場合、Cスタイルのキャストも正しいことを行います。


より詳しい情報


1保証されません。で何が起こるかについての保証はほとんどありませんreinterpret_cast。私が知っているすべての実装は、同じアドレスを変更せずに提供するだけです。

于 2012-02-04T05:56:03.770 に答える