c++typeIDキーワードの使用


typeidキーワード
注意:typeIDはオペレータであり、関数ではありません。これはサイゼフに似ている)
運転中に変数の種類名を知ると、typeID(変数).name()が使用できます。
すべてのコンパイラが出力する「int」や「float」などの名前ではないので、このようなコンパイラはこのように使えます。

 int ia = 3;
 if(typeid(ia) == typeid(int))
 {
   cout <<"int" <<endl;
 }
RTTI(Run-Time Type Identiftication)-運転時タイプ識別
typeidの神秘的なベールを開く前に、まずRTTI(Run-time Type Identification、実行時タイプの識別)を調べてみます。基本的な指針または参照によって対象の実際の派生タイプを取得できます。すなわち、オブジェクトをベースクラスに向けるポインタまたは参照で操作することを許可するプログラムは、「これらのポインタまたは参照オブジェクト」の実際の派生タイプを取得することができます。
C++には、RTTIをサポートするために2つのオペレータが提供されています。キャストとtypeID
  • dynamic_castは運行時刻にタイプ変換を許可し、プログラムを一つのクラスの階層構造の中で安全にタイプを変換することができます。これに対応してもう一つの非安全な変換オペレータstatic_もあります。cast、これは本文の討論の重点ではないので、ここではもう詳しく述べません。興味があるのは自分で資料を調べられます。
  • typeIDはC++のキーワードの一つであり、sizofのようなオペレータと同じです。typeID操作符の戻り結果はtype_といいます。infoの標準ライブラリタイプのオブジェクトの参照(先頭ファイルのtypeinfoで定義されています。後でvsとgccライブラリのソースコードを見てみます。)は、次の表式の2種類があります。
  • 実現メカニズムと使用テクニック
    タイプinfo類オブジェクト種別判別
    対象カテゴリ判別分析
    式の種類がクラスタイプで、少なくとも虚数関数が含まれている場合、typeID演算子は式のダイナミックタイプを返します。実行時に計算します。
    そうでなければ、typeIDオペレータは式の静的なタイプを返します。コンパイル時に計算できます。
    ISO C++標準は正確にtype_を定義していません。infoはコンパイラに関する正確な定義をしていますが、標準では次の4つの操作を提供する必要があります。infoファイルのソースコード)
    演算
    説明
    t 1==t 2
    2つのオブジェクトt 1とt 2のタイプが同じであれば、trueに戻る。そうでないとfalseに戻ります
    t 1!=t 2
    2つのオブジェクトt 1とt 2のタイプが異なる場合、trueに戻る。そうでないとfalseに戻ります
    t.name()
    タイプC-style文字列を返します。タイプ名はシステム関連の方法で生成されます。
    t 1.before(t 2)
    t 1がt 2より前のブックの値であるかどうかを返す。
    タイプinfoクラスは、ユーザがベースクラスとして利用できるように、public虚構関数を提供する。そのデフォルトのコンストラクタとコピーコンストラクタと割り当てられたオペレータは、prvateと定義されていますので、type_を定義またはコピーすることはできません。infoタイプのオブジェクトです。プログラムでtype_を作成しますinfoオブジェクトの唯一の方法はtypeID操作子を使うことです。infoの友元。タイプinfoのnameメンバー関数は、対応するタイプ名を表すためにC-styleの文字列を返しますが、このリターンのタイプ名は、プログラムで使用されている対応するタイプ名と必ずしも一致していないことに注意してください。これはコンパイラの実装によって定められています。標準は、各タイプごとに一意の文字列を返すことだけが必要です。
    タイプinfo類ソースコード
    sudo find/-name typeinfo.hを使ってソースを検索します。
    
    #ifndef _TYPEINFO
    #define _TYPEINFO
    
    #include <exception>
    
    namespace std
    {
    
     class type_info
     {
     public:
    
      virtual ~type_info();
      { return __name[0] == '*' ? __name + 1 : __name; }
    
    
      bool before(const type_info& __arg) const
      { return __name < __arg.__name; }
    
      bool operator==(const type_info& __arg) const
      { return __name == __arg.__name; }
    
      bool operator!=(const type_info& __arg) const
      { return !operator==(__arg); }
    
      virtual bool __is_pointer_p() const;
    
      virtual bool __is_function_p() const;
    
     protected:
      const char *__name;
    
      explicit type_info(const char *__n): __name(__n) { }
    
     private:
      type_info& operator=(const type_info&);
      type_info(const type_info&);
     };
    
    } // extern "C++"
    #endif
    例1-基本データタイプ
    以下の表には、typeID演算子を使用した表式の値が表示されます。
    
     int a;
     double b;
     char * c;
     long d;
    演算
    説明
    typeID(a)=typeid(int)
    true
    typeid(a)=typeid(float)
    false
    typeID(a)=typeid(int*)
    false
    typeID(b)=typeid(double)
    true
    typeID(b)=typeid(float)
    false
    typeID(b)=typeid(long double)
    false
    typeID(c)=typeid(char*)
    true
    typeID(c)=typeid(char)
    false
    typeID(c)=typeid(string)
    false
    typeID(d)=typeid(long)
    true
    typeID(d)=typeid(int)
    false
    操作符typeidが戻ってくるのはtype_です。infoクラス(データタイプのシステムクラスを記述するための)オブジェクトの参照。このオペレータは、クラスなどの所定のデータタイプを含む、表式およびタイプ名に使用できます。
    例2-クラスオブジェクト
    
    class base
    {
    public :
      void m(){cout<<"base"<<endl;}
    };
    class derived : public base
    {
    public:
      void m(){cout<<"derived"<<endl;}
    };
    例2で定義した2つのクラスに基づいて、次のようなポインタを定義すると仮定します。
    
    base * p = new derived;
    以下の表では、typeID操作の結果を示します。
    演算
    説明
    typeID(p)=typeid(base*)
    true
    typeID(p)=typeid(derid*)
    false
    typeID(*p)=typeid(base)
    true
    typeid(*p)=typeid(derid)
    false
    表式typeID(p)についても同様にpはbase*タイプのポインタなので、typeID(p)=typeid(base*)が本当で、typeid(p)=typeid(*)が偽です。式typeid(*p)に対しては、この時点では基質が多形性を持たないため、*pはコンパイル期間タイプで計算され、コンパイル期間*pはベースオブジェクトとなりますので、式typeid(*p)=typeid(devid)は偽、typeid(*p)=typeid(base)は本物です。
    例3-虚数関数付きのベースクラス
    
    class base
    {
    public :
      virtual void m(){cout<<"base"<<endl;}
    };
    class derived : public base
    {
    public:
      void m(){cout<<"derived"<<endl;}
    };
    本例で示したように、2つのクラスのベースクラスとdersivedクラスを定義したと仮定します。これらの2つのクラスの定義に基づいて、ポインタを以下のように定義します。
    
    base * p = new derived;
    以下の表では、typeID操作の結果を示します。
    演算
    説明
    typeID(p)=typeid(base*)
    true
    typeID(p)=typeid(derid*)
    false
    typeID(*p)=typeid(base)
    false
    typeid(*p)=typeid(derid)
    true
    表式typeID(p)は、pがベース*タイプのポインタなので、typeID(p)=typeid(base*)が本物で、typeid(p)=typeid(*)が偽です。また、式typeID(*p)については、ベース類が多形性を持っているため、typeid(*p)を計算する際には、実行時pが指す実際のタイプによって計算されますが、本例ではpが派生類のオブジェクトを指すため、式typeid(*p)=typeid(derved)が真、typeID(*p)=typeid(base)となります。
    異常処理bad_typeID
    
    class bad_typeid : public exception
     {
     public:
      bad_typeid () throw() { }
    
      // This declaration is not useless:
      // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
      virtual ~bad_typeid() throw();
    
      // See comment in eh_exception.cc.
      virtual const char* what() const throw();
     };
    } // namespace std

    以上はc+typeIDキーワードの使用の詳細です。c+typeIDキーワードに関する資料は他の関連記事に注目してください。