C++ typeidf演算子 type_infoクラス ダウンキャスト クロスキャスト 書いて覚えるための初心者自己中記事
typeid 演算子を使うと型の情報をGETできる。
使い方は
typeid ( 値 or 型 )
返り値は
type_infoクラスのconst参照です。
type_infoクラスは
#include <typeinfo> が必要です。
このクラスのメンバ関数に
name
というのがあって
型情報をconst char* で返してくれる。
使い方は
typeid( 値or 型 ) . name ( )
で出来る。
今までもあったのかな?
なんか違和感。
あ、そっか。typeid 演算子だけど返り値がtype_infoクラスの参照だから
メンバ関数name を使えるのか。
そうかそうか。
void ShowType(const ostream& ostr) { cout << typeid(ostr).name() << endl; //typeid演算子とメンバ関数name } int main() { fstream fstr; ofstream ofstr; stringstream sstr; ostringstream osstr; ShowType(cout); ShowType(fstr); ShowType(ofstr); ShowType(sstr); ShowType(osstr); system("pause"); }
//output
class std::basic_ostream<char,struct std::char_traits<char> >
class std::basic_fstream<char,struct std::char_traits<char> >
class std::basic_ofstream<char,struct std::char_traits<char> >
class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> >
class std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >
なんかごちゃごちゃ出てきた。
型の情報が出てる。
ここで使ったShowType関数は 仮引数がostream& なのでcout 以外はアップキャストになるが型の情報は失われていない。
というか型の情報が失われるようならアップキャストからの仮想関数とか無理だもんね。
このように、実行時に動的に得られる型情報のことを
実行時型情報
( Run-Time Type Information : RTTI )
というそうです。
typeid演算子の返り値をtype_infoクラスオブジェクトで直接受け取るのはだめだそうで
const type_info& ti = typeid(fstr); //OK type_info& ti = typeid(fstr); //error const type_info ti = typeid(fstr); //error
const参照なら大丈夫。
テキストだと、typeidの結果がtype_info の派生クラスの可能性があると書いてる。
そうなのか。
ダウンキャストについて
アップキャストの逆、派生クラスへのポインタや参照キャスト。
とりあえず、危険らしい。
理由は、本来の型と無関係なクラスへダウンキャストされる可能性があるから。
・・・?
string Hoge(ostream& ostr) { ostringstream& osstr = static_cast<ostringstream&>(ostr); //ここでダウンキャストしている osstr.str(""); osstr << "Hoge" << flush; return osstr.str(); } int main() { cout << Hoge(cout) << endl; system("pause"); }
このダウンキャストは失敗する。
コンパイルは出来るが実行時にエラーになる。
もともとのcout (ostream ) でostringstream のメンバ関数 str() を使えないから。
ダウンキャストしたとしてもダウン先の派生クラス独自のメンバは使えないということか。
これって、ダウンキャストが失敗したというよりダウンキャストした後で、出来ないことをやらせようとしたからエラーになったってことだよね。
ここでダウンキャスト可能かどうかのためにはRTTI を用いる必要がある。
それを利用したキャスト演算子があって、
dynamic_cast
です。
ほかのキャスト演算子(static_cast など) と同じで
今回の場合は
ostringstream& osstr = dynamic_cast<ostringstream&>(ostr); //ここでダウンキャストしている
こうします。
このキャスト演算子はキャスト失敗の際に行動してくれる。
参照で失敗した時とポインタで失敗した時で行動内容が変わるが、
参照で失敗した場合 bad_cast 例外がthrow される
ポインタで失敗した場合 ヌルポインタが返ってくる
といった感じ。
参照の場合はダウンキャストをtry で囲って下にcatchを設けて
catch ( const bad_cast& e){ }
とかですね。
このキャスト演算子 dynamic_cast はダウンキャスト以外でも使用可能で
とにかくキャストに失敗したらエラー吐く便利なもの。
streamクラス
[ istream ] [ ostream ]
↑ ↑ ↑ ↑ ↑ ↑
[ ifstream ] [ istringstream ] [ iostream ] [ ofstream ] [ ostringstream ]
↑ ↑
[ fstream ] [ stringstream ]
キャストは上がって下がっても可能
fstream から istream へ
その後
istream から( iostream経由で) ostreamへ
fstream fstr; istream& istr = fstr; ostream& ostr = dynamic_cast<ostream&>(istr);
こんな感じ。
istream から( iostream経由で) ostreamへのキャストではダウンキャストがあるからdynamic_castを使っているのかな。
このダウンしてからアップする部分をクロスキャストを言うらしい。
ここまで。