c++のRTTI紹介

5078 ワード

本文はc++のRTTIの基本的な用法を紹介し,RTTIの実現原理を初歩的に研究した.
1.RTTIとは
RTTIは、ポインタまたはバインドされたオブジェクトを参照する動的タイプを判断するランタイムタイプ識別(runtime type identification)であり、2つの演算子によって実現される.
dynamic_castは、ベースクラスポインタまたは参照を派生クラスのポインタまたは参照に安全に変換する.
typeidは式のタイプを返します.
2.なぜRTTIを使うのか
オブジェクトのタイプ情報が必要な場合、たとえば非虚関数を使用する必要がある場合は、現在のポインタでバインドされているオブジェクトのダイナミックタイプを知る必要があります.
3.RTTIの使い方
dynamic_castは、安全なダウンシフト(type-safe downcast)に使用されます.注意点:演算子が作用するオブジェクトには、虚関数が含まれている必要があります.
ポインタタイプに作用すると、変換に失敗してNULLを返します.参照に使用する場合、参照が空にならないため、変換に失敗した場合std::bad_cast異常.
class base{

public:

    base(int val):bv(val){}

    virtual void printVal(){printf("base::printVal   bv=%d
", bv);} int bv; };
class derive:public base{ public: derive(int val, double d):base(val), dv(d){} void printVal(){ printf("derive::printVal dv= %f
", dv); } double dv; }; int main(){ derive d(10, 20.00); base *b = &d; assert(derive *dp = dynamic<derive*>(b)); return 0; }

typeidは任意の式またはタイプに作用し、演算オブジェクトがクラスタイプに属していないか、または虚関数を含まない場合、演算オブジェクトの静的タイプを返します.そうしないと、typeidは実行時まで動的タイプを決定します.typeidが返す値はtype_infoタイプオブジェクト、type_info::name()はタイプの名前を返します.もちろんこれはコンパイラに関連しています.一般的には、2つのオブジェクトのダイナミックタイプが同じかどうか、または特定のオブジェクトが指定されたタイプかどうかを判断するために使用されます.
printf("%s
", typeid(derive).name());

6derive
4.作用原理
ではdynamic_castとtypeidはどのようにオブジェクトの実際のタイプを知っているのか、『inside the c++object model』でタイプ情報が虚関数テーブルの最初のslotにあることを繰り返し言及しているが、これはコンパイラ実装とは大きな違いがあり、私の前の文章によると、gcc実装の虚関数テーブルに置かれているのはすべて虚関数であり、タイプ情報はないことが分かった.
derive d(10, 20.00);

printf("deirve address: %x
", &d); 

一歩一歩debug、
 derive d(10, 20.00);
(gdb) n
printf("deirve address: %x", &d);
(gdb)
deirve address: bffff2a0
(gdb) x/4a 0xbffff2a0
0xbffff2a0:   0x80487e0 <_ZTV6derive+8>   0xa 0x0 0x40340000
dのアドレスは0 xbffff 2 a 0であり、1つ目は虚関数テーブルポインタ0 x 80487 e 0であり、虚関数テーブルが_ZTV 6 deriveから8バイト先、ZTV 6 deriveって何?
(gdb) x/16a  0x80487d0
0x80487d0: 0x0 0x40340000 0x0 0x80487fc <_ZTI6derive>
0x80487e0 <_ZTV6derive+8>:  0x80486ca <_ZN6derive8printValEv>  0x0 0x0 0x8048810 <_ZTI4base>
0x80487f0 <_ZTV4base+8>: 0x8048674 <_ZN4base8printValEv> 0x72656436 0x657669   0x804a068 <_ZTVN10__cxxabiv120__si_class_type_infoE@@CXXABI_1.3+8>
0x8048800 <_ZTI6derive+4>:  0x80487f4 <_ZTS6derive>  0x8048810 <_ZTI4base>    0x73616234 0x65
ZTV 6 deriveの値は0であり,後にtypeinfoの構造が0 x 804 a 068を指し,class type infoのオブジェクトであることは明らかです.従ってgccは虚関数テーブルの前に2バイトを追加し,1番目は0であり,2番目のポインタはtype infoの構造を指す.
このtype infoの構造はいったいどんなものなのか、私も資料を見つけていません.知っている学生が私と交流してくれることを望んでいます.ありがとうございます.