This article is from the Object-Oriented Technology FAQ, by Bob Hathaway firstname.lastname@example.org with numerous contributions by others.
In C++, virtual functions provide polymorphism. This is because a polymorphic
object (pointer or reference (or such parameter)) is assignment compatible with
any object of a derived class. Is this polymorphism in itself? Objects
can take on objects of different forms (the derived classes), but of what use
is it? To make any difference, the differing forms must have some effect. In
dynamically typed languages, polymorphic objects are passed messages and will
respond in whatever way the object has defined (usually starting from its most
derived class and working its way up). But for static objects, a virtual
function is invoked. This is the stored method from the derived class that
overrode the virtual method from its base class, providing specialized behavior
for the polymorphic object; and hence, polymorphism. This common pure
statically typed example is, of course, an example of inclusion polymorphism,
subclass polymorphism to be more specific (see section 2.1). Pure statically
typed subtype polymorphism, as provided in Emerald, can be implemented
similarly [Black 86].