You use virtual functions when you want to override a certain behavior (read method) for your derived class rather than the one implemented for the base class and you want to do so at run-time through a pointer to the base class.
The classic example is when you have a base class called Shape and concrete shapes (classes) that derive from it. Each concrete class overrides (implements a virtual method) called Draw().
The class hierarchy is as follows:

The following snippet shows the usage of the example; it creates an array of Shape class pointers wherein each points to a distinct derived class object. At run-time, invoking the Draw() method results in the calling of the method overridden by that derived class and the particular Shape is drawn (or rendered).
Shape *basep[] = { &line_obj, &tri_obj,
&rect_obj, &cir_obj};
for (i = 0; i < NO_PICTURES; i++)
basep[i] -> Draw ();
The above program just uses the pointer to the base class to store addresses of the derived class objects. This provides a loose coupling because the program does not have to change drastically if a new concrete derived class of shape is added anytime. The reason is that there are minimal code segments that actually use (depend) on the concrete Shape type.
The above is a good example of the Open Closed Principle of the famous SOLID design principles.