この例では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スタイルのキャストは、成功する次の最初のキャストとして定義されます。
const_cast
static_cast
static_cast
、 それからconst_cast
reinterpret_cast
reinterpret_cast
、 それからconst_cast
ご覧のとおり、astatic_cast
は前に試さreinterpret_cast
れているので、この場合、Cスタイルのキャストも正しいことを行います。
より詳しい情報
1保証されません。で何が起こるかについての保証はほとんどありませんreinterpret_cast
。私が知っているすべての実装は、同じアドレスを変更せずに提供するだけです。