1. ホーム
  2. c++

[解決済み] レギュラーキャスト vs スタティックキャスト vs ダイナミックキャスト [重複]の比較

2022-02-18 11:05:11

質問

私は20年近くCとC++のコードを書いているが、これらの言語のある側面がよく理解できていない。私は当然ながら通常のキャスト、すなわち

MyClass *m = (MyClass *)ptr;

があちこちにありますが、他にも2種類のキャストがあるようで、その違いがわかりません。以下のコードの行は何が違うのでしょうか?

MyClass *m = (MyClass *)ptr;
MyClass *m = static_cast<MyClass *>(ptr);
MyClass *m = dynamic_cast<MyClass *>(ptr);

解決方法は?

静的キャスト

static_cast` は、基本的に暗黙の変換を逆変換したい場合に使用しますが、いくつかの制限や追加もあります。static_cast` は実行時のチェックを行いません。これは、特定の型のオブジェクトを参照していることが分かっていて、チェックが不要な場合に使用されるはずである。例
void func(void *data) {
  // Conversion from MyClass* -> void* is implicit
  MyClass *c = static_cast<MyClass*>(data);
  ...
}

int main() {
  MyClass c;
  start_thread(&func, &c)  // func(&c) will be called
      .join();
}

この例では、あなたが MyClass オブジェクトを生成するため、これを確認するための実行時チェックは必要ありません。

ダイナミックキャスト

dynamic_cast` は、オブジェクトの動的な型がわからない場合に便利です。参照されるオブジェクトが、キャストされた型を基底クラスとして含んでいない場合、null ポインタを返す (参照にキャストした場合、その場合は `bad_cast` 例外がスローされる)。
if (JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {
  ...
} else if (ExprStm *e = dynamic_cast<ExprStm*>(&stm)) {
  ...
}

を使用することはできません。 dynamic_cast ダウンキャスト(派生クラスへのキャスト)した場合、引数の型が多相性でない場合。たとえば、次のコードは無効です。 Base は仮想関数を含んでいません。

struct Base { };
struct Derived : Base { };
int main() {
  Derived d; Base *b = &d;
  dynamic_cast<Derived*>(b); // Invalid
}

アップキャスト(基底クラスへのキャスト)は、常に次の2つの方法で有効です。 static_castdynamic_cast また、アップキャストは暗黙のうちに変換されるため、キャストは不要です(ベースクラスがアクセス可能であると仮定して、つまり、それは public を継承している)。

レギュラーキャスト

これらのキャストは、C-styleキャストとも呼ばれます。C スタイルのキャストは、基本的に C++ キャストのシーケンスをさまざまに試し、最初に動作した C++ キャストを採用するのと同じです。 dynamic_cast . もちろん、この方法は、すべての const_cast , static_castreinterpret_cast を使用しないため、安全ではありません。 dynamic_cast .

また、C言語スタイルのキャストでは、このようなことができるだけでなく、プライベートなベースクラスへのキャストを安全に行うことができ、一方、"equivalent" static_cast というシーケンスでは、コンパイル時にエラーが発生します。

簡潔であるため、Cスタイルのキャストを好む人もいます。私は、数値のキャストのみにこの方法を使用し、ユーザー定義型が含まれる場合は、より厳密なチェックを行うため、適切なC++のキャストを使用します。