A virtual function makes its class a polymorphic base class. Derived classes can override virtual functions. Virtual functions called through base class pointers/references will be resolved at run-time. That is, the dynamic type of the object is used instead of its static type:
Derived d; Base& rb = d; // if Base::f() is virtual and Derived overrides it, Derived::f() will be called rb.f();
A pure virtual function is a virtual function whose declaration ends in =0:
class Base { // ... virtual void f() = 0; // ... }
A pure virtual function makes the class it is defined for abstract. Abstract classes cannot be instantiated. Derived classes need to override/implement all inherited pure virtual functions. If they do not, they too will become abstract.
In C++, a class can define a pure virtual function that has an implementation. (What that’s good for is debatable.)