元ブログ, 【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<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);```
コメントアウトしたキャストがコンパイル通らなかったものです。
どのくらい正解していましたか?
コンパイルが通った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までどうぞ!
誰かのお役に立てば。