Reputation: 253
In my program I have a class named Entity. Another class Invader inherits Entity. Since I want to have 4 different kinds of invaders, I declare classes Invader1, Invader2, Invader3 and Invader4 which inherit from Invader. Now I declare a Entity pointer type vector to store all Invaders like:
entities.push_back(new Invader4());
entities.push_back(new Invader3());
entities.push_back(new Invader2());
entities.push_back(new Invader1());
entities.push_back(new Invader0());
When I check the type of the element in entities at runtime, say
typeid(*entities->at(index))
It may return one of the 4 kinds of invaders. In entities there are also other objects which inherit Entity. So i just want to check if the type of the object is Invader or not, I don't want to know if it is Invader1, Invader2, etc.
How I can achieve this?
Upvotes: 4
Views: 2436
Reputation: 227548
There will be many ways to do this in C++, but the fundamental problem is that once you have to start querying elements in a container that is supposed to be polymorphic you might as well give up on the idea of using polimorphism. The whole point of having collections of polymorphic elements is that you can treat them all the same. So if you have a vector<Entity*>
you should only treat its elements as Entity*
s. If you find that you need to call some Invader
-like functions on an Entity
, then you are better off holding a container of Invader*
too (using the same pointers as for the original container).
Upvotes: 6
Reputation: 16007
Just asking this question usually means you're actually missing a virtual function in your interface.
If you have something like:
if (myEntity->Type() == TypeInvader)
{
static_cast<Invader*>(myEntity)->invade();
}
You can almost certainly refactor it by adding
virtual void tryInvade() {/* normally, entities don't invade*/}
in your Entity and
virtual void tryInvade() {invade(); /*but invaders do!*/}
in your Invader class.
Another option is to never "lose" the type of your entities. If you don't want to use virtual functions for cases like this, chances are, that you shouldn't store those entities by referring to their base-class pointers, but as pointers to the classes you actually want to use. That is, you just keep the type of the entity around instead of asking for it later. This would probably be a sign that you shouldn't have used inheritance tho, since you would have violated the liskov substition principle respective storage.
Upvotes: 1
Reputation: 32542
You could check whether dynamic_cast<Invader*>(entities->at(index))
returns not NULL
(as it would result in a NULL
pointer when the pointer is not pointing to an object whose class is derived from Invader
).
See this link for some documentation.
Upvotes: 3
Reputation: 22644
Create an Invader
class which inherits from Entity
. Have your Invader1
, Invader2
, etc. classes inherit from Invader
.
You may then add a virtual bool IsInvader() const;
which returns false
in Entity
and true
in Invader
.
Upvotes: 2