Introduction
A frequently asked question is: “How can I identify/check the type of an object in C++ at run-time?” Let me show you by resolving a simple problem!
Complete the program to display “Bark!” in the first call of CFoo::AnimalSays and “Miaou!” in the second one.
class Animal {/*...*/}; class Dog : public Animal {/*...*/}; class Cat : public Animal {/*...*/}; class CFoo { public: void AnimalSays(Animal*) {/*...*/} }; int main(int argc, char* argv[]) { Dog rex; Cat kitty; CFoo foo; foo.AnimalSays(&rex); foo.AnimalSays(&kitty); return 0; }
In other words, you have to find a method to verify at run-time whether the function CFoo::AnimalSays takes, as an argument, a pointer to an object of type Dog or a pointer to an object of type Cat.
One First Try
The first idea is to add a member variable that stores info about the type.
#include <iostream> class Animal { public: enum AnimalType {TypeDog, TypeCat}; }; class Dog : public Animal { public: Dog() : m_type(TypeDog) {} const AnimalType m_type; }; class Cat : public Animal { public: Cat() : m_type(TypeCat) {} const AnimalType m_type; }; class CFoo { public: void AnimalSays(Animal*); }; int main(int argc, char* argv[]) { Dog rex; Cat kitty; CFoo foo; foo.AnimalSays(&rex); foo.AnimalSays(&kitty); return 0; } void CFoo::AnimalSays(Animal* pAnimal) { if(((Dog*)pAnimal)->m_type == Animal::TypeDog) std::cout << "Bark! "; else if(((Cat*)pAnimal)->m_type == Animal::TypeCat) std::cout << "Miaou! "; }
Now, please take a look at the CFoo::AnimalSays function implementation and imagine that you have not only two but fifty-two animal types (in other words, classes derived from Animal)! Quite ugly! It will be hard to write it with no errors and it also will be hard to read/modify/maintain. However, there can be even worse solutions…