C++ ⇒ VBA 書いて覚えるための初心者自己中記事

C++ ⇒ VBA 勉強の履歴を付けるというかノート代わりに使ってます

C++ typeidf演算子 type_infoクラス ダウンキャスト クロスキャスト  書いて覚えるための初心者自己中記事

typeid 演算子を使うと型の情報をGETできる。

 

使い方は

typeid (   値 or 型   )

返り値は

type_infoクラスのconst参照です。

 

type_infoクラスは

#include <typeinfo> が必要です。

このクラスのメンバ関数

name

というのがあって

型情報をconst char* で返してくれる。

 

使い方は

typeid( 値or 型 ) . name ( ) 

で出来る。

typeid 演算子の後にメンバ関数

今までもあったのかな?

なんか違和感。

 

あ、そっか。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を使っているのかな。

このダウンしてからアップする部分をクロスキャストを言うらしい。

 

 ここまで。