メインコンテンツへスキップ

static_cast, dynamic_cast, reinterpret_castで結果が変わる例

·612 文字
技術解説 C++

static_cast, dynamic_cast, reinterpret_castの計算結果がすべて違う値になる例がぱっと思いつかなかったのでメモ。

以下のコードは、3つのキャストの計算結果が異なる例である。

#include <iostream>
#include <cstdlib>

class A1 {virtual void f(){};};
class A2 {virtual void g(){};};
class B : public A1, public A2 {};

#define DEBUG_PRINT(val)  std::cout << #val << "\t:" << (val) << std::endl

int main(int argc, char* argv[]) {
  A2* a2 = new A2;

  DEBUG_PRINT(a2);
  DEBUG_PRINT(static_cast<B*>(a2));
  DEBUG_PRINT(dynamic_cast<B*>(a2));
  DEBUG_PRINT(reinterpret_cast<B*>(a2));

  delete a2;
  return EXIT_SUCCESS;
}

コンパイルして実行すると、以下のように成る。

$ g++ cast_test.cpp
$ ./a.out
a2      :0x55eb8db7ae70
static_cast<B*>(a2)     :0x55eb8db7ae68
dynamic_cast<B*>(a2)    :0
reinterpret_cast<B*>(a2)        :0x55eb8db7ae70

static_cast, dynamic_cast, reinterpret_castの計算結果がそれぞれ異なっている。

static_castでは、元のアドレス値から8を引た値になった。A2Bの継承関係から”8″という値が静的に決められている。実行時は変数の中身を見ないでキャストするので、Bのインスタンスでないa2に対しても構わず引き算を実行している。

dynamic_castでは、実行時にa2の継承関係を調べて結果を決める。a2Bのインスタンスではないので、動的キャストに失敗してnullptrが返る。

reinterpret_castは、計算前後でアドレス値が変化しない1reinterpret_castの危険性がよく分かる。


  1. 厳密に言うと、reinterpret_cast前後でアドレス値が変わるかどうかは処理系依存である。C++11では、reintepret_castで別の型に変換して、再度reinterpret_castで元の型に戻しても値が変わらないことだけが記載されている。 ↩︎



komori-n
著者
komori-n

Related

利かずの駒並べ|理論編
·3046 文字
技術解説 C++ パズル 将棋
利かずの駒並べ|実践編
·640 文字
やってみた C++ パズル 将棋
マクロ定数からカッコを剥ぎ取る
·234 文字
技術解説 C言語