« VC++2008のRegex | トップページ | VC++2008のキャスト演算子(その2) »

2008年11月28日 (金)

VC++2008のキャスト演算子(その1)

C++で分かりにくいのがキャスト演算子(static_cast/dynamic_cast/reinterpret_cast/const_cast)の使い分けである。
手元にあるC++の教科書「C++ 実践プログラミング」(Steve Oualline著 オライリー)は600ページぐらいあって単なる入門書ではないが、キャスト演算子の違いについて詳しく書いていない。

以下は復習を兼ねてのメモ書きです(その1)ではstatic_castとdynamic_castとの区別

「C++ 実践プログラミング」を資料1、「Boost  C++をチューンアップする最先端ライブラリ」(ビョルン・カールソン(著) 村上雅章(訳) ピアソン・エデュケーション)を資料2、として参照している。

使用したVC++は「Visual C++ 2008 Express Edition SP1」


[1] テストプログラム

class A {
public:
  virtual void a(){cout<<"A\n";}
};

class AA : public A {
public:
  void aa(){cout<<"AA\n";}
};

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)
dynamic_cast<AA*>(aa)->aa(); // (3)
dynamic_cast<AA*>(ab)->aa(); // (4)

[1-1] プロジェクトのプロパティ「ランタイム型情報を有効にする」を「いいえ(/GR-)」に設定したとき、(3)(4)でコンパイル時警告(warning C4541)は出るが、とりあえずコンパイルは正常終了する。
実行してみると、

・ (2)が実行できる。クラスAAのメンバー関数aa()が実行される。(これは結構すごい!)
・ (3)がランタイムエラーとなる。(プログラムを作った本人は、変数aaがAAのオブジェクトを保持していることに自信?があるのですけど)

[1-2] プロジェクトのプロパティ「ランタイム型情報を有効にする」を「はい(/GR)」に設定したとき、コンパイル時警告は無い。
実行してみると、

・ (1)(2)(3)(4)すべて実行できる。しかも、クラスAAのメンバー関数aa()が実行される。
・ (2)はともかく(4)が実行できてしまうのは何のためのランタイム型情報でdynamic_castなのだろうか。


[2] クラスAAだけ定義を変えた。

class AA : public A {
  int  aai;
public:
  void aa(){ cout<<"AA"<<aai<<"\n"; }
  AA() { aai = 1; }
};

[2-1] ランタイム型情報を有効にして実行してみると、

・ (1)(3)は期待通りの動きをする。
・ (2)はやはり実行できるが、aaiの値としてメチャクチャな値を使っている。static_castが危険であるといわれるのはこのあたりにあるのだろう。
(4)はランタイムエラーとなる。これが(自分の理解では)本来のdynamic_castの動きである
(2)と(4)の動きの違いがstatic_castとdynamic_castとの違いなのだろう。

[2-2] (4)のランタイムエラーについて。文献1は「不正な変換を試みると、例外がスローされ」(P434)としているが、文献2は「ポインタ型に対してdynamic_castが用いられ、変換に失敗した場合にはnullポインタが返される」(P52)としています。
C++の規格としてはどちらが正しいかは分かりませんが、(4)に関して言うと文献2の動きをしています。dynamic_cast自体は例外をスローせず、nullポインタを返しています。

« VC++2008のRegex | トップページ | VC++2008のキャスト演算子(その2) »

パソコン・インターネット」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: VC++2008のキャスト演算子(その1):

« VC++2008のRegex | トップページ | VC++2008のキャスト演算子(その2) »