VC++2008のキャスト演算子(その2)
(その2)はreinterpret_castとstatic_cast。今までreinterpret_castを使ったことがなかったので、これは勉強メモです。
[1] テストプログラムは(その1)と同じ
class A {
public:
virtual void a(){ cout<<"A\n"; }
};
class AA : public A {
int aai;
public:
void aa(){ cout<<"AA"<<aai<<"\n"; }
AA() { aai = 1; }
};
class AB : public A {
public:
void ab(){ cout<<"AB\n"; }
};
A* a = new A();
A* aa = new AA();
A* ab = new AB();
static_cast<AA*>(aa)->aa(); // (1)
static_cast<AA*>(ab)->aa(); // (2)
reinterpret_cast<AA*>(aa)->aa(); // (3)
reinterpret_cast<AA*>(ab)->aa(); // (4)
[1-1] 「ランタイム型情報を有効にする」を「はい」としてコンパイル&実行してみると、
・ (1)(3)は期待通りの動きをする。
・ (2)(4)も実行できてしまう。どちらもaaiの値としてメチャクチャな値を使っている。
・ この結果だけ見るとstatic_castとreinterpret_castは同じ作用を持っているように見え、違いは何かわかりません。
[1-2] reinterpret_castによる無関係ポインタ間の無理矢理変換機能。
同じプログラムに別のクラスZを導入する。
class Z {
int zi;
public:
void z(){ cout<<"Z"<<zi<<"\n"; }
Z(){ zi = 9; }
};
static_cast<Z*>(aa)->z(); // (5)
reinterpret_cast<Z*>(aa)->z(); // (6)
・ (5)がコンパイルエラー(C2440)になる。static_castではA*からZ*に変換できないのでreinterpret_castを使え、というメッセージがでる。つまり(6)のやり方。
・ (6)は確かにコンパイルができ実行もできるが、ziとしてメチャクチャな値を使っている。普通はこんなことはしないと思う。
[1-3] reinterpret_castはポインタ型と整数型との相互変換の機能もあるようだ。
unsigned long ad1 = static_cast<unsigned long>(aa); // (7)
unsigned long ad2 = reinterpret_cast<unsigned long>(aa); // (8)
reinterpret_cast<AA*>(ad2)->aa(); // (9)
・ (7)はコンパイルエラー(C2440)になる。
・ (8)はコンパイルができ実行もできる。(8)で整数化し、(9)で元に戻す。(6)よりは使い道があるかもしれない。(ポインタ型がunsigned longに収まるという前提。)