C++ でダイナミックキャストを使用する

胡金庫 2023年10月12日
C++ でダイナミックキャストを使用する

この記事では、C++ でダイナミックキャストを利用する方法について複数のメソッドを紹介します。

基底クラスポインタから派生クラスへの変換に dynamic_cast を使用する

dynamic_cast を使用すると、プログラマは継承階層を越えてクラスへのポインタや参照を変換することができます。例えば、基底クラスポインタを派生クラスポインタにキャストして、プログラマが派生クラスのメンバ関数を呼び出すことができます。

dynamic_cast はランタイム型情報(RTTI)機能の一部であり、コンパイル時ではなく実行時にオブジェクトの型にアクセスする方法を提供します。

なお、dynamic_castintfloat のようなプリミティブ型間の変換には使えないことに注意してください。さらに、dynamic_cast は基底クラスに少なくとも 1つの仮想メンバ関数が含まれている場合にのみ使用すべきです。次の例では、新しい Base クラスポインタを宣言し、それを Derived クラスへの新しいポインタにキャストします。dynamic_cast は null ポインタを返すので、もしキャストに失敗した場合は、if 文の中に条件として式を記述することができます。

#include <iostream>
#include <typeinfo>

using std::cout;
using std::endl;

struct Base {
  virtual ~Base() = default;
};

struct Derived : public Base {};

int main() {
  Base *bp = new Derived;
  if (Derived *dp = dynamic_cast<Derived *>(bp)) {
    cout << "Successful cast - can use the pointer to 'Derived' object dp"
         << endl;
  }

  delete bp;
  return EXIT_SUCCESS;
}

出力:

Successful cast - can use the pointer to 'Derived' object dp

プログラマは if セクションスコープ内のオブジェクトに安全にアクセスし、必要に応じて Derived クラスのメンバメソッドを呼び出すことができます。ただし、Derived クラスの型を Base にキャストしているので、13 行目では new 演算子の後に Derived を指定しています。

#include <iostream>
#include <typeinfo>

using std::cout;
using std::endl;

struct Base {
  virtual ~Base() = default;
};

struct Derived : public Base {};

int main() {
  Base *bp = new Base;
  if (Derived *dp = dynamic_cast<Derived *>(bp)) {
    cout << "Successful cast - can use the pointer to 'Derived' object dp"
         << endl;
  }

  delete bp;
  return EXIT_SUCCESS;
}

RTTI の機能のもう一つの部分は typeid 演算子で、これは与えられた式の型を返すものです。これは、次のコードサンプルで示されているように、複数の式の型を比較するために利用することができます。なお、typeid 演算子を利用する際には、<typeinfo> ヘッダを含める必要があります。

#include <iostream>
#include <typeinfo>

using std::cout;
using std::endl;

struct Base {
  virtual ~Base() = default;
};

struct Derived : public Base {};

int main() {
  Base *bp = new Derived;
  if (Derived *dp = dynamic_cast<Derived *>(bp)) {
    cout << "Successful cast - can use the pointer to 'Derived' object dp"
         << endl;
    if (typeid(*bp) == typeid(*dp)) {
      cout << "bp and dp are of same type" << endl;
    }
  }

  delete bp;
  return EXIT_SUCCESS;
}

出力:

Successful cast - can use the pointer to 'Derived' object dp
bp and dp are of same type
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook

関連記事 - C++ Cast