LoginSignup
3
3

More than 5 years have passed since last update.

【c++】決定版!*_castまとめ

Last updated at Posted at 2015-03-10

元ブログ, 【c++】決定版!*_castまとめ - 技術は熱いうちに打て!

C++の主な名前付きcast


const_cast:constと宣言されたものに書き込めるようにする。
static_cast:的確に定義された暗黙の変換の逆の変換を行う。
reinterpret_cast:ビットパターンの意味を変えてしまう。
dynamic_cast:動的なクラス階層の移動をチェックする。

プログラミング言語C++第4版より

さて、理解出来たでしょうか?
理解出来た人は見なくても良いかもしれないです笑

検証

まず、2つのカスタムクラスを作成します。
BaseHogeとSubHogeです。
その名の通りSubHogeはBaseHogeを継承しています。
そして4つの変数を用意しました。
一番下はポリモーフィズムのために用意しています。

int integer = 10;
BaseHoge* base = new BaseHoge();
SubHoge* sub = new SubHoge();
BaseHoge* polBase = new SubHoge();

テストコード

// from integer
int intToIntWithStatic = static_cast<int>(integer);
BaseHoge* intToBaseWithStatic = static_cast<BaseHoge*>(integer);
SubHoge* intToSubWithStatic = static_cast<SubHoge*>(integer);

int intToIntWithReinterpret = reinterpret_cast<int>(integer);
BaseHoge* intToBaseWithReinterpret = reinterpret_cast<BaseHoge*>(integer);
SubHoge* intToSubWithReinterpret = reinterpret_cast<SubHoge*>(integer);

int intToIntWithConst = const_cast<int>(integer);
BaseHoge* intToBaseWithConst = const_cast<BaseHoge*>(integer);
SubHoge* intToSubWithConst = const_cast<SubHoge*>(integer);

int intToIntWithDynamic = dynamic_cast<int>(integer);
BaseHoge* intToBaseWithDynamic = dynamic_cast<BaseHoge*>(integer);
SubHoge* intToSubWithDynamic = dynamic_cast<SubHoge*>(integer);

// from base
int baseToIntWithStatic = static_cast<int>(base);
BaseHoge* baseToBaseWithStatic = static_cast<BaseHoge*>(base);
SubHoge* baseToSubWithStatic = static_cast<SubHoge*>(base);

int baseToIntWithReinterpret = reinterpret_cast<int>(base);
BaseHoge* baseToBaseWithReinterpret = reinterpret_cast<BaseHoge*>(base);
SubHoge* baseToSubWithReinterpret = reinterpret_cast<SubHoge*>(base);

int baseToIntWithConst = const_cast<int>(base);
BaseHoge* baseToBaseWithConst = const_cast<BaseHoge*>(base);
SubHoge* baseToSubWithConst = const_cast<SubHoge*>(base);

int baseToIntWithDynamic = dynamic_cast<int>(base);
BaseHoge* baseToBaseWithDynamic = dynamic_cast<BaseHoge*>(base);
SubHoge* baseToSubWithDynamic = dynamic_cast<SubHoge*>(base);

// from sub
int subToIntWithStatic = static_cast<int>(sub);
BaseHoge* subToBaseWithStatic = static_cast<BaseHoge*>(sub);
SubHoge* subToSubWithStatic = static_cast<SubHoge*>(sub);

int subToIntWithReinterpret = reinterpret_cast<int>(sub);
BaseHoge* subToBaseWithReinterpret = reinterpret_cast<BaseHoge*>(sub);
SubHoge* subToSubWithReinterpret = reinterpret_cast<SubHoge*>(sub);

int subToIntWithConst = const_cast<int>(sub);
BaseHoge* subToBaseWithConst = const_cast<BaseHoge*>(sub);
SubHoge* subToSubWithConst = const_cast<SubHoge*>(sub);

int subToIntWithDynamic = dynamic_cast<int>(sub);
BaseHoge* subToBaseWithDynamic = dynamic_cast<BaseHoge*>(sub);
SubHoge* subToSubWithDynamic = dynamic_cast<SubHoge*>(sub);

// from polBase
int polBaseToIntWithStatic = static_cast<int>(polBase);
BaseHoge* polBaseToBaseWithStatic = static_cast<BaseHoge*>(polBase);
SubHoge* polBaseToSubWithStatic = static_cast<SubHoge*>(polBase);

int polBaseToIntWithReinterpret = reinterpret_cast<int>(polBase);
BaseHoge* polBaseToBaseWithReinterpret = reinterpret_cast<BaseHoge*>(polBase);
SubHoge* polBaseToSubWithReinterpret = reinterpret_cast<SubHoge*>(polBase);

int polBaseToIntWithConst = const_cast<int>(polBase);
BaseHoge* polBaseToBaseWithConst = const_cast<BaseHoge*>(polBase);
SubHoge* polBaseToSubWithConst = const_cast<SubHoge*>(polBase);

int polBaseToIntWithDynamic = dynamic_cast<int>(polBase);
BaseHoge* polBaseToBaseWithDynamic = dynamic_cast<BaseHoge*>(polBase);
SubHoge* polBaseToSubWithDynamic = dynamic_cast<SubHoge*>(polBase);

さて、お気付きの人もいると思いますが、一部はコンパイルすら通らないものもあります。

少し考えてから先に進むとより面白いかもしれません。

答え合わせ

さて、ではまずコンパイルの通らないものを紹介していきます。(C++11で実験しました。)


// from integer
int intToIntWithStatic = static_cast&lt;int&gt;(integer);
# BaseHoge* intToBaseWithStatic = static_cast&lt;BaseHoge*&gt;(integer);
# SubHoge* intToSubWithStatic = static_cast&lt;SubHoge*&gt;(integer);

int intToIntWithReinterpret = reinterpret_cast&lt;int&gt;(integer);
BaseHoge* intToBaseWithReinterpret = reinterpret_cast&lt;BaseHoge*&gt;(integer);
SubHoge* intToSubWithReinterpret = reinterpret_cast&lt;SubHoge*&gt;(integer);

# int intToIntWithConst = const_cast&lt;int&gt;(integer);
# BaseHoge* intToBaseWithConst = const_cast&lt;BaseHoge*&gt;(integer);
# SubHoge* intToSubWithConst = const_cast&lt;SubHoge*&gt;(integer);

# int intToIntWithDynamic = dynamic_cast&lt;int&gt;(integer);
# BaseHoge* intToBaseWithDynamic = dynamic_cast&lt;BaseHoge*&gt;(integer);
# SubHoge* intToSubWithDynamic = dynamic_cast&lt;SubHoge*&gt;(integer);

// from base
# int baseToIntWithStatic = static_cast&lt;int&gt;(base);
BaseHoge* baseToBaseWithStatic = static_cast&lt;BaseHoge*&gt;(base);
SubHoge* baseToSubWithStatic = static_cast&lt;SubHoge*&gt;(base);

# int baseToIntWithReinterpret = reinterpret_cast&lt;int&gt;(base);
BaseHoge* baseToBaseWithReinterpret = reinterpret_cast&lt;BaseHoge*&gt;(base);
SubHoge* baseToSubWithReinterpret = reinterpret_cast&lt;SubHoge*&gt;(base);

# int baseToIntWithConst = const_cast&lt;int&gt;(base);
BaseHoge* baseToBaseWithConst = const_cast&lt;BaseHoge*&gt;(base);
# SubHoge* baseToSubWithConst = const_cast&lt;SubHoge*&gt;(base);

# int baseToIntWithDynamic = dynamic_cast&lt;int&gt;(base);
BaseHoge* baseToBaseWithDynamic = dynamic_cast&lt;BaseHoge*&gt;(base);
SubHoge* baseToSubWithDynamic = dynamic_cast&lt;SubHoge*&gt;(base);

// from sub
# int subToIntWithStatic = static_cast&lt;int&gt;(sub);
BaseHoge* subToBaseWithStatic = static_cast&lt;BaseHoge*&gt;(sub);
SubHoge* subToSubWithStatic = static_cast&lt;SubHoge*&gt;(sub);

# int subToIntWithReinterpret = reinterpret_cast&lt;int&gt;(sub);
BaseHoge* subToBaseWithReinterpret = reinterpret_cast&lt;BaseHoge*&gt;(sub);
SubHoge* subToSubWithReinterpret = reinterpret_cast&lt;SubHoge*&gt;(sub);

# int subToIntWithConst = const_cast&lt;int&gt;(sub);
# BaseHoge* subToBaseWithConst = const_cast&lt;BaseHoge*&gt;(sub);
SubHoge* subToSubWithConst = const_cast&lt;SubHoge*&gt;(sub);

# int subToIntWithDynamic = dynamic_cast&lt;int&gt;(sub);
BaseHoge* subToBaseWithDynamic = dynamic_cast&lt;BaseHoge*&gt;(sub);
SubHoge* subToSubWithDynamic = dynamic_cast&lt;SubHoge*&gt;(sub);

// from polBase
# int polBaseToIntWithStatic = static_cast&lt;int&gt;(polBase);
BaseHoge* polBaseToBaseWithStatic = static_cast&lt;BaseHoge*&gt;(polBase);
SubHoge* polBaseToSubWithStatic = static_cast&lt;SubHoge*&gt;(polBase);

# int polBaseToIntWithReinterpret = reinterpret_cast&lt;int&gt;(polBase);
BaseHoge* polBaseToBaseWithReinterpret = reinterpret_cast&lt;BaseHoge*&gt;(polBase);
SubHoge* polBaseToSubWithReinterpret = reinterpret_cast&lt;SubHoge*&gt;(polBase);

# int polBaseToIntWithConst = const_cast&lt;int&gt;(polBase);
BaseHoge* polBaseToBaseWithConst = const_cast&lt;BaseHoge*&gt;(polBase);
# SubHoge* polBaseToSubWithConst = const_cast&lt;SubHoge*&gt;(polBase);

# int polBaseToIntWithDynamic = dynamic_cast&lt;int&gt;(polBase);
BaseHoge* polBaseToBaseWithDynamic = dynamic_cast&lt;BaseHoge*&gt;(polBase);
SubHoge* polBaseToSubWithDynamic = dynamic_cast&lt;SubHoge*&gt;(polBase);``` 

コメントアウトしたキャストがコンパイル通らなかったものです。
どのくらい正解していましたか?

コンパイルが通ったcastの結果

それでは通ったもの達の結果を見ていきましょう。

// CCLOG("%d, %p", integer, &integer);
10, 0x7fff5d214a1c

// CCLOG("%p", base);
0x7f9351d37f60

// CCLOG("%p", sub);
0x7f9351d39250

// CCLOG("%p", polBase);
0x7f9351d39270

intToIntWithStatic 10

intToIntWithReinterpret 10
intToBaseWithReinterpret 0xa
intToSubWithReinterpret 0xa

baseToBaseWithStatic 呼び出したクラス自身のポインタ
baseToSubWithStatic 0x7f9351d37f60

baseToBaseWithReinterpret 0x7f9351d37f60
baseToSubWithReinterpret 0x7f9351d37f60

baseToBaseWithConst 0x7f9351d37f60

baseToBaseWithDynamic 0x7f9351d37f60
baseToSubWithDynamic NULL

subToBaseWithStatic 0x7f9351d39250
subToBaseWithStatic 0x7f9351d39250

subToBaseWithReinterpret 0x7f9351d39250
subToSubWithReinterpret 0x7f9351d39250

subToSubWithConst 0x7f9351d39250

subToBaseWithDynamic 0x7f9351d39250
subToSubWithDynamic 0x7f9351d39250

// from polBase
polBaseToBaseWithStatic 0x7f9351d39270
polBaseToSubWithStatic 0x7f9351d39270

polBaseToBaseWithReinterpret 0x7f9351d39270
polBaseToSubWithReinterpret 0x7f9351d39270

polBaseToBaseWithConst 0x7f9351d39270

polBaseToBaseWithDynamic 0x7f9351d39270
polBaseToSubWithDynamic 0x7f9351d39270

まとめ

面白い所で言うと以下ですかね。

・integerからのreinterpret_castのコンパイルが全て通っている
・逆にオブジェクトからintegerへのコンパイルは全て通らない
・static_castのbase自身へのcastが呼び出したクラスのポインタになる
・constは自分自身のポインタ以外はエラーになる(用途的に当たり前ですね)

※ちなみに reinterpret_castのポインタへのキャストはintegerの値を16進数にした値でした。
なので、integerが10なら0xaだし、15だったら0xfと言った具合ですね。

他にこういう実験してくれとかあれば@daiki1003までどうぞ!

誰かのお役に立てば。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3