Take the following C++ for example.
vector<Animal> listAnimal;
class Fish : Animal ...
class Mammal : Animal ...
class Bird : Animal ...
If I then add them all to the list, and then grab them off the list arbitrary I wont know which subclass I am dealing with. I in Java I could do getClass()
or thefish instanceof Fish
. How do I do this in C++?
You shouldn't need to know what type of sub-class you're dealing with. You're not doing polymorphism right if you need to check the type of class you're dealing with. The whole point of polymorphism is to reduce if's and make your code a lot more flexible.
There are some cases where you need to know, and you can use RTTI for that. However I recommend not to, especially if you require a lot of performance (such as games or graphics programs).
Use the typeid
operator to get information about a class, and to determine if a class is a specific type.
For example:
Animal* animal1 = new Cat;
if(typeid(animal1) == typeid(Cat))
{
cout << "animal1 is a: " << typeid(Cat).name();
}
Then use a static_cast
to cast it down the hierarchy.
Animal* animal1 = new Cat;
if(typeid(animal1) == typeid(Cat))
{
Cat* cat = static_cast<Cat*>(animal1);
cat->scratchTheLivingHellOutOfYou();
}
Alternatively you can use a dynamic_cast
which is much safer, but much slower than a typeid/static_cast. Like so:
Animal* animal1 = new Cat;
if(Cat* cat = dynamic_cast<Cat*>(animal1)
{
cat->scratchTheLivingHellOutOfYou();
}
dynamic_cast
is slower simply because it has to do a little extra work than just testing if it's a specific type and casting. i.e. dyanmic_cast
is not equivalent to typeid/static_cast
, but it almost is.
Imagine a hierarchy further than 2 levels deep, for example:
class Animal { /* ... */ }; // Base
class Cat : public Animal { /* ... */ }; // 2nd level
class Tiger : public Cat { /* ... */ }; // 3rd level
Let's say that in the Cat class, a method specific to all Cats is called: scratchTheLivingHellOutOfYou()
. Let's also say that: I have a list of Animals and I want to call scratchTheLivingHellOutOfYou()
for every Cat in the list (this includes classes that derive from the class Cat). If the typeid
operator and static_cast
is used, this would not achieve what is required, since typeid
only checks for the current type and does not care about the hierarchy. For this, you have to use a dynamic_cast
, since it will check if a class is derived from a base-class, and then cast up/down the hierarchy accordingly.
You can see this simple example, in C++, here. Here is the output of the program:
USING TYPEID
*scratch*
meoyawnn!
RAWR
USING DYNAMIC_CAST
*scratch*
meoyawnn!
*scratch*
RAWR
Therefore, you can clearly see that dynamic_cast
does a lot more work than a simple typeid
and static_cast
. Since dynamic_cast
looks up the hierarchy to see if it is a specific type. Simply put... dynamic_cast
can cast up and down the hierarchy. Whereas a typeid
and static_cast
can only cast down the hierarchy to a specific type.
I thought I'd mention that if dynamic_cast
fails it will return a NULL pointer, or throw an exception if you're using it with references.
dynamic_cast
should only be used if you're not sure the object will be the type you're converting to. If you, as a programmer, know whatever you're casting is 100% going to be that type then use static_cast
, e.g. if you know animal1 is going to be a Cat
then static_cast
is more appropriate. If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With