0

そこから派生した 2 つの子クラスを持つ基本クラスがあります。

class A {};
class B : public A {};
class C : public A {};

次のようなベクトルを使用して、クラス A メンバーのコレクションへのポインターを持つ別のクラスがあります。

vector<A*> *m_collection;

クラス B または C のオブジェクトを作成し、push_back を使用してコレクションに追加します。

B *myb = new B();
m_collection->push_back(myb);

次に、コレクションをループして「typeid」を使用してチェックしようとしますが、常に基本クラス (A) が返されます。正確なタイプを知ることはできませんか?

ありがとうございました!

4

2 に答える 2

4

まず、new を使用してベクトルを動的に作成する理由はほとんどありません。簡単に言うと:

vector<A*> m_collection;

次に、基本クラスに 1 つまたは 2 つの仮想関数を与える必要があります。仮想デストラクタは良いスタートです:

class A {
   public:
     virtual ~A() {}
};

これがないと、次のようなコードを安全に書くことができません。

m_collection.push_back( new B );
delete m_collection[0];

これを行うと、実行時の型情報も有効になります。ただし、オンにするtypeidことは、C++ が RTTI を使用するのを好む方法ではありません。使用する必要がありますdynamic_cast

m_collection.push_back( new B );    // or new A or new C
if ( C * c = dynamic_cast<C *>( m_collection[0] ) ) {
   c->CFunc():  // function in C
}
else if ( B * b = dynamic_cast<B *>( m_collection[0] ) ) {
   b->BFunc():  // function in B
}
else if ( A * a = dynamic_cast<A *>( m_collection[0] ) ) {
   a->AFunc():  // function in A
}
else {
  throw "unknown type";
}

ただし、一般的には、ディスパッチには RTTI よりも仮想関数メカニズムを使用する方が適切です。

于 2010-02-09T17:47:56.257 に答える
0

typeid に関しては、基本クラス (A) に仮想関数が必要です (通常、vtable は std::type_info 構造体の近くにあります)。次に、オブジェクトを逆参照する必要がありますtypeid(*b)

于 2010-02-09T17:50:07.470 に答える