C++ supports object oriented programming and procedural programming, a allows the two to be mixed.
OOP uses virtual functions and you must access the objects indirectly (using pointers or references). Procedural programming doesn't require any fancy rules.
foo() is not virtual, so the pointer or reference's foo() will always be used directly.
print() is virtual, and the actual objects print() will be used if accessed thru any pointer or reference to one of it's base classes.