Polymorphism allows objects of different types to be treated as objects of a general type. There are two main types: static polymorphism achieved through function overloading and operator overloading at compile time, and dynamic polymorphism achieved through virtual functions and overridden functions at runtime. Virtual functions allow late binding where the function called depends on the object type. Pure virtual functions must be defined in derived classes.