static_cast、dynamic_cast、const_cast、reinterpret_cast はいつ使用すればよいですか? 質問する

static_cast、dynamic_cast、const_cast、reinterpret_cast はいつ使用すればよいですか? 質問する

以下の適切な使用法は何ですか?

特定のケースでどちらを使用するかをどのように決定するのでしょうか?

ベストアンサー1

static_cast

static_castは、最初に使用しようとするキャストです。これは、型間の暗黙的な変換 (intへの変換float、または へのポインターなどvoid*) などを実行し、明示的な変換関数 (または暗黙的な変換関数) を呼び出すこともできます。多くの場合、明示的に指定する必要はありませんが、構文は と同等であり、使用を避ける必要があるstatic_castことに注意してください(詳細は後述)。ただし、 は安全であり、コンストラクターを呼び出すことが保証されています。T(something)(T)somethingT(something, something_else)

static_cast継承階層を介してキャストすることもできます。上向き (基底クラスへ) にキャストする場合は必要ありませんが、下向きにキャストする場合は、virtual継承を介してキャストしない限り使用できます。ただし、チェックは行われず、static_cast実際にはオブジェクトの型ではない型に階層を下ってキャストすることは未定義の動作です。

const_cast

const_castconstを使用して、変数を削除したり、変数に追加したりできます。他の C++ キャストでは、これを削除できません ( でさえも)。以前の値を変更すると、元の変数が の場合にのみ未定義になるreinterpret_castことに注意してください。を使用して宣言されていないものへの参照から を削除する場合は安全です。たとえば、 に基づいてメンバー関数をオーバーロードする場合に便利です。また、メンバー関数オーバーロードを呼び出すなど、オブジェクトに追加するために使用することもできます。constconstconstconstconstconst

const_castは にも同様に機能しますがvolatile、あまり一般的ではありません。

dynamic_cast

dynamic_castは、ポリモーフィズムの処理にのみ使用されます。任意のポリモーフィック型へのポインターまたは参照を、他のdynamic_cast任意のクラス型にキャストできます (ポリモーフィック型には、宣言または継承された少なくとも 1 つの仮想関数があります)。これは、下向きのキャストだけでなく、横向きのキャストや別のチェーンの上のキャストにも使用できます。 は、目的のオブジェクトを検索し、可能であればそれを返します。検索できない場合は、nullptrポインターの場合は戻り、std::bad_cast参照の場合はスローします。

dynamic_castただし、いくつかの制限があります。継承階層 (いわゆる「恐ろしいダイヤモンド」) に同じタイプのオブジェクトが複数あり、継承を使用していない場合は機能しません。また、パブリック継承のみを通過できます。つまり、継承virtualを通過することは常に失敗します。ただし、このような形式の継承はまれであるため、これが問題になることはほとんどありません。protectedprivate

reinterpret_cast

reinterpret_castは最も危険なキャストであり、慎重に使用する必要があります。これは、ある型を別の型に直接変換します。たとえば、あるポインターから別のポインターに値をキャストしたり、ポインターを に格納したりint、その他さまざまな厄介な処理を行います。 で得られる唯一の保証は、reinterpret_cast通常、結果を元の型にキャストすると、まったく同じ値が得られることです (ただし、中間の型が元の型よりも小さい場合は除きますreinterpret_cast)。では実行できない変換も多数あります。これは、生のデータ ストリームを実際のデータに変換したり、整列されたデータへのポインターの下位ビットにデータを格納したりするなど、特に奇妙な変換やビット操作に悪用されることがよくあります。これらのケースについては、 を参照してくださいstd::bit_cast

C スタイルキャストと関数スタイルキャスト

C スタイルのキャストと関数スタイルのキャストは、それぞれ(type)objectまたはを使用したキャストでありtype(object)、機能的に同等です。これらは、次のうち最初に成功するものとして定義されます。

  • const_cast
  • static_cast(ただし、アクセス制限は無視)
  • static_cast(上記参照)、その後const_cast
  • reinterpret_cast
  • reinterpret_cast、 それからconst_cast

したがって、場合によっては他のキャストの代わりとして を使用できますが、 に退化する可能性があるため非常に危険です。が成功するか失敗するかreinterpret_castが確実でない限り、明示的なキャストが必要な場合は を使用してください。static_castが成功するreinterpret_cast場合でも、より長く、より明示的なオプションを検討してください。

C スタイルのキャストは、 を実行するときにアクセス制御も無視しますstatic_cast。つまり、他のキャストでは実行できない操作を実行できます。ただし、これはほとんど場当たり的なものであり、私にとっては C スタイルのキャストを避けるもう 1 つの理由です。

std::bit_cast[C++20]

std::bit_castは、ソース オブジェクト (その表現) のビットとバイトを、ターゲット タイプの新しいオブジェクトに直接コピーします。これは、標準に準拠したタイプのパンニングの方法です。 と書いている場合は*reinterpret_cast<SomeType*>(&x)、代わりに を使用することをお勧めしますstd::bit_cast<SomeType>(x)

std::bit_castは で宣言されています<bit>。オブジェクトは同じサイズで、簡単にコピー可能である必要があります。まだ C++20 を使用できない場合は、 を使用してmemcpyソース値を目的の型の変数にコピーします。

おすすめ記事