\n |
[ トップページ ]
[ ____CommandPrompt ]
[ ____JScript ]
[ ____MySQL ]
[ ____Cygwin ]
[ ____Java ]
[ ____Emacs ]
[ ____Make ]
[ ____Perl ]
[ ____Python ]
[ ____OpenGL ]
[ ____C# ]
[ ____StyleSheet ]
[ ____C++ ]
[ ____Winsock ]
[ ____Thread ]
[ ____VisualStudio ]
[ ____C ]
[ ____Win32API ]
[ ____Lua ]
[ ____PhotoShop ]
ヘッダ検索
■ cast(キャスト)
型変換
// int -> double
double dval = (double)ival;
//
long -> int *
int *iptr = (int *)lval;
reinterpret_cast : ptr 同士の変換 | ptr < -> int( ptr アドレスは不変 )
■ reinterpret_cast
互換性のないポインタ同士のキャストに利用する。
reinterpret_cast は偽者の型でもキャストできてしまう。
安全性という視点では使うのは良くない。
// int * -> long *
lptr = reinterpret_cast< lptr>( iptr );
dynamic_cast : CBase から CDerived への型保障キャスト (逆)?
POINT
upcast : CDerived -> CBase
downcast : CBase -> CDerived
POINT
cpp スタイルのキャストを利用することで, キャストの意図を明確にする
WARNING
キャストは 飽くまで [ 型がこうである ] と コンパイラに言い聞かせるだけ。
( 保障は一切ない )
だから Cast は最低限にするべき ( C++ ならば Template で代用すること )
void onClick( Gui *gui ) {
Button *b = reinterpret_cast< Button >( gui );
}
POINT
アセンブラでは型という概念がない
アドレスを指定して, Data を Add, するだけ
中身( アドレスの指す先の bit 列 が Integer )を意味するかどうかは プログラマが責任ををもってしていた
しかしそれば手間で、中身を間違うという事故があったため、型というルールができた。
// キャストの内容によってメモリ上の値が変わることも、不変な場合もある
// VisualStudio のメモリウィンドウで確認できる。
int i = 128; // MEM IMG [ 0x 80 00 00 00 ]
int i2 = i; // MEM IMG [ 0x 80 00 00 00 ]
float f = i; // MEM IMG [ 0x 00 00 00 43 ] // ここが43となる点に注意
結論
アドレス( という数値 )を格納する場合は, 変更されない.
なぜなら adr の指す先の Object をこう読んでね とい言うようなもの.
数値型の場合は, 型によって表現方法が異なるので, bit 列が変更される.
base obj を derive obj の ptr に cast して操作すれば,問題があることを意識する
■ const_cast
const, volatile 外し
// cint * -> int *
iptr = const_cast< int *>ciptr;
// cint -> int
ival = const_cast< int>cival; // ERR( ptr 以外はだめ ? )
■ static_cast
DESC
[ 暗黙の型変換 ]がある場合のみ変換できる。
[ 安全な型変換 ]
暗黙の型変換があれば変換
安全な cast を意味するので, c_style_cast より積極的に利用するべき
OK
// void * < -> any *
-> down cast の場合, 派生先の領域にアクセスするのは危険かも
// upcast
Bcls *p = static_cast< Bcls *>( pDcls );
// const をつける
int p = 10;
const int cp = static_cast< const int >( p );
cp = 20; // error: assignment of read-only variable `cp'
static_cast:
int -> long
lval = static_cast< long>(ival); // OK
void *-> int
ival = static_cast< void *>ival; // ERROR
ERROR
Foo *p = static_cast< Foo *>( pBar ); // 継承関係のない cls
3. dynamic_cast
ptr が指す obj の型を取得( obj がどの mem func を support しているか確認という意味 )
WARNING
polymorphic cls のみ( ∵ vtbl 必要 )
4. reinterpret_cast
指定された型に[ 読み替える ]のみ
-> 無理やり別の型に変換する.
void *p = reinterpret_cast< void *>( &fooObj ); // ptr ads は不変
WARNING
多重継承していると 問題が起きる
POINT
// コンパイルエラーで出力される内容が正しい型変換を意味する
MSG:: c style cast || static_cast が必要です
■ dynamic_cast
POINT
オブジェクトがあるインターフェイスをサポートするか調べるときに使う。
派生クラスから基底クラスへダウンキャストする時に使う。
[ ptr がさす obj の型を取得 ] として考えれば OK
dynamic_cast が使用できるのは, 仮想メンバ関数をもつ場合
Base *p = new Derive();
Derive *d = dynamic_cast< Derive *>(p);
Another *p = new Another();
// キャストできない場合は NULL を返す
Derive *d = dynamic_cast< Derive *>(p);
DESC
base -> derive ptr への cast
constructor 時に dynamic_cast< derive *>(this) としても 変換は不可能
construct 時に 処理をわけることは不可能
WARNING
class が virtual 関数を含む必要あり == polymorphic class の必要あり( compile err )
|
|
NINJAIDX 12