web-dev-qa-db-ja.com

C ++の「typeid」と「typeof」

C++のtypeidtypeofの違いは何だろうと思っています。私が知っていることは次のとおりです。

  • typeidは、C++ヘッダーファイル typeinfo で定義されている type_info のドキュメントに記載されています。

  • typeofは、CのGCC拡張機能およびC++ Boost ライブラリで定義されています。

また、ここに、typeidが期待したものを返さないことを発見した場所で作成したテストコードテストを示します。どうして?

main.cpp

#include <iostream>  
#include <typeinfo>  //for 'typeid' to work  

class Person {  
    public:
    // ... Person members ...  
    virtual ~Person() {}  
};  

class Employee : public Person {  
    // ... Employee members ...  
};  

int main () {  
    Person person;  
    Employee employee;  
    Person *ptr = &employee;  
    int t = 3;  

    std::cout << typeid(t).name() << std::endl;  
    std::cout << typeid(person).name() << std::endl;   // Person (statically known at compile-time)  
    std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)  
    std::cout << typeid(ptr).name() << std::endl;      // Person * (statically known at compile-time)  
    std::cout << typeid(*ptr).name() << std::endl;     // Employee (looked up dynamically at run-time  
                                                       // because it is the dereference of a pointer
                                                       // to a polymorphic class)  
 }  

output:

bash-3.2$ g++ -Wall main.cpp -o main  
bash-3.2$ ./main   
i  
6Person  
8Employee  
P6Person  
8Employee
129
Tim

C++言語にはtypeofのようなものはありません。コンパイラ固有の拡張機能を確認する必要があります。 GCCのtypeofについて話している場合、キーワードdecltypeを介してC++ 11に同様の機能が存在します。繰り返しますが、C++にはそのようなtypeofキーワードはありません。

typeidは、実行時に型識別情報を返すC++言語演算子です。基本的にtype_infoオブジェクトを返します。これは、他のtype_infoオブジェクトと同等のオブジェクトです。

返されるtype_infoオブジェクトの唯一の定義されたプロパティは、同等および同等ではないことです。つまり、異なるタイプを記述するtype_infoオブジェクトは等しくないものを比較し、同じタイプを記述するtype_infoオブジェクトは等しく比較する必要があります。それ以外はすべて実装定義です。さまざまな「名前」を返すメソッドは、人間が読み取れるものを返すことは保証されておらず、まったく返されることも保証されていません。

また、上記はおそらく、同じタイプにtypeidを連続して適用すると、異なるtype_infoオブジェクトを返す可能性があることを(標準では明示的に言及していないように思われますが).

166
AnT

2つの主な違いは次のとおりです。

  • typeofはコンパイル時の構成体であり、コンパイル時に定義された型を返します
  • typeidはランタイム構造であるため、値のランタイムタイプに関する情報を提供します。

typeofリファレンス: http://www.delorie.com/gnu/docs/gcc/gcc_36.html

typeidリファレンス: https://en.wikipedia.org/wiki/Typeid

41
JaredPar

typeid は実行時に動作し、オブジェクトの実行時タイプを記述するオブジェクトを返します。これは RTTI(run -time type information) クラスに保存されます。また、実行時の型情報を持つクラスへのポインタが指定されていない場合、式のコンパイル時の型または型名を指定できます。

typeof はGNU拡張であり、コンパイル時に任意の式のタイプを提供します。これは、たとえば、複数の型で使用される可能性のあるマクロで一時変数を宣言する場合に役立ちます。 C++では、通常 templates を代わりに使用します。

26
Brian Campbell

追加の質問に答える:

typeidの次のテストコードは、正しいタイプ名を出力しません。どうしましたか?

何も問題はありません。表示されるのは、型名の文字列表現です。標準のC++では、コンパイラにクラスの正確な名前を強制的に強制するのではなく、適切なものを決定するのは実装者(コンパイラベンダー)のみです。要するに、名前はコンパイラ次第です。


これらは2つの異なるツールです。 typeofは式の型を返しますが、標準ではありません。 C++ 0xには、decltypeと呼ばれるものがあり、これは同じ仕事をしています。

decltype(0xdeedbeef) number = 0; // number is of type int!
decltype(someArray[0]) element = someArray[0];

一方、typeidは多相型で使用されます。たとえば、catanimalを派生させるとしましょう。

animal* a = new cat; // animal has to have at least one virtual function
...
if( typeid(*a) == typeid(cat) )
{
    // the object is of type cat! but the pointer is base pointer.
}
20
AraK

typeidは、要求時に実行時にデータのタイプを提供します。 Typedefは、後で説明するように新しい型を定義するコンパイル時の構造です。 C++出力にはtypeofがありません(内接コメントとして表示)。

std::cout << typeid(t).name() << std::endl;  // i
std::cout << typeid(person).name() << std::endl;   // 6Person
std::cout << typeid(employee).name() << std::endl; // 8Employee
std::cout << typeid(ptr).name() << std::endl;      // P6Person
std::cout << typeid(*ptr).name() << std::endl;     //8Employee
4

Boostデマングルを使用して、素敵な名前を実現できます。

#include <boost/units/detail/utility.hpp>

そして何かのような

To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this);
3
Patrick K