Suppose i want a program that can manage different animals using a Base-Class/Interface
I think that when you're thinking about
dynamic_cast, you're envisioning the
makeYourSound(Animal* a) function as consisting of two hundred
if...else if blocks, each one testing for and handling a particular type of animal. Yeah, that's slow and unmaintainable. Don't do it.
dynamic_cast is good for, really, is optional interfaces. A particular thing that some animals can do, but not others.
if(Eagle* e = dynamic_cast<Eagle*>(a)) is a code smell, and a bad one.
if(IFly* f = dynamic_cast<IFly*>(a)) smells much less. It avoids code duplication, it avoids polluting the base class with meaningless methods and tap-dancing around how to handle non-flying animals, and it describes more precisely in your code what you are trying to do.
The advantage of virtual function-based polymorphism is that the object is fully in charge, something that appeals greatly to OO purists. But in some cases, as a practial programmer, you don't want the object to be in control, just to tell your code a bit more about itself so it can be properly dealt with. More nuanced guidelines, like the OCP, are more widely applicable, and they don't rule out
dynamic_cast, just indiscriminate use of it.