You are a victim of what is known as object slicing. C++ is different from Java and C# in the way it handle its objects. In C# for example every user define type is managed as a reference when you create a new instance, and only primitive types and structures are handled as values, This means that in Java or C# when you assign an object, you are only assigning references, for instance:
Object a = new Object();
Object b = a;
Will result in both a and b pointing to the same object (The one created when we assigned a).
In C++ the story is different. you can create an instance of an object in the heap or the stack. and you can pass said objects by reference, by pointer or by value.
If you asssign references or pointers, it will behave similar to C# and Java. But if you assign an object by value, that is you assign the actual object and not a pointer or a reference, a new copy of the object will be created. Every user define type in C++ is copyable by default.
When you have inheritance and polymorphism involved, this copy behaviour creates an issue, because when you copy a child type into a parent type, the copy that will be created will only contains the portion of information for the parent type in the child, thus losing any polymorphism you may have.
In your example when you copy a Cat object into a Animal object, only the Animal part of the cat is copied, thats why you lose your polymorphism, the virtual table is no more. If you base class is abstract in any way this wont even be possible.
The solution, if you want to retain polymorphism, is to pass the object by pointer or reference instead of by value. You can create the object in the heap and assign that pointer, you can take the address of the object in the stack and assing that pointer, or you could just take the reference of the object and assign that instead.
The lesson to be learned here is to NEVER pass or assign by value objects with any sort of polymorphism or you will end up slicing it.