In this exercise, we re-inject type checking that should have been left there in the first place...
Very cool.
An important OOP feature is type casting that converts one object type to another. Type conversions play an important role in polymorphism. It allows a program to treat objects of one type as another so that the code can utilize certain general or specific features within the class hierarchy. Unlike other OOP languages—such as Java—that always verify the safety of a type conversion using runtime type information (RTTI), C++ offers two kinds of type conversions: static_cast, which verifies the correctness of conversion at compile time, and dynamic_cast, which verifies type safety at runtime using RTTI. static_cast is much more efficient because runtime type checking by dynamic_cast is an expensive operation (e.g., 90 times slower than static_cast on average). For this reason, many performance critical applications like web browsers, Chrome and Firefox in particular, prohibit dynamic_cast in their code and libraries, and strictly use static_cast. However, the performance benefit of static_cast comes with a security risk because information at compile time is by no means sufficient to fully verify the safety of type conversions. In particular, upcasting (casting a derived class to its parent class) is always safe, but downcasting (casting a parent class to one of its derived classes) may not be safe because the derived class may not be a subobject of a truly allocated object in downcasting. Unsafe downcasting is better known as bad-casting or type-confusion.
Yes, we are still in the Middle Ages of Coding, with barely adequate programming languages, EULAs, witches, "here be dragons" and mandragore sprinkled all over everywhere, and bad reflexes (performance >> security) are still prevalent. But we are slowly getting there.