A more object-oriented approach would consist of relying on polymorphism instead of continuously switching on an enumerator value representing a type.
To follow this approach, first, define an abstract class, Animal, that specifies the member functions its subclasses should implement:
class Animal {
public:
virtual std::string GetGermanTranslation() const = 0;
virtual float GetMaxSpeed() const = 0;
virtual ~Animal() = default;
};
Then, publicly derive from this class and override the virtual member functions GetGermanTranslation() and GetMaxSpeed().
For example, for Cat:
class Cat: public Animal {
public:
std::string GetGermanTranslation() const override { return "Katze"; };
float GetMaxSpeed() const override { return 30; };
};
Then, similarly for Dog:
class Dog: public Animal {
public:
std::string GetGermanTranslation() const override { return "Hund"; };
float GetMaxSpeed() const override { return 40; };
};
You can analogously define the Fish class.
Finally, having a pointer or reference to an Animal object, you just call the corresponding virtual member functions:
void displayAnimal(const Animal& animal) {
std::cout << "The " << animal.GetGermanTranslation();
std::cout << " runs at " << animal.GetMaxSpeed() << '\n';
}
As you can see, there is no more switching on an enumerator that represents a type for distinguishing the different animals.
You can call this function, displayAnimal(), with different Animal objects:
auto cat = std::make_unique<Cat>();
displayAnimal(*cat);
auto dog = std::make_unique<Dog>();
displayAnimal(*dog);