Tony
Tony

Reputation: 253

Check the type of derived class

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

Answers (4)

juanchopanza
juanchopanza

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

ltjax
ltjax

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

moooeeeep
moooeeeep

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

Daniel Daranas
Daniel Daranas

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

Related Questions