Где и как правильно использовать спецификатор virtual в С++?
Это называется "динамический полиморфизм". 
Виртуальные методы полезны тем, что вызывая метод через ссылку или указатель на базовый класс, на самом деле вы вызываете метод дочернего класса:class B {
public:
    virtual void f() {}
    ...
}

class D: public B{
public:
    void f(){}
    ...
}
...
doF(D());
...
void doF(const B& b){
    b.f();// вызовется D::f() 
}
 Если написать вместо тела виртуальной функции "=0;", то получится чисто виртуальный класс. Это уже полноценный аналог абстрактного класса в джаве. А если сделать все методы чисто виртуальными и не делать полей-данных, то получится аналог интерфейса.
Виртуальным обязательно должен быть деструктор у класса, который создаётся для наследования. Иначе сделав так:B *d = new D();
delete d; вы вызовете только деструктор базового класса.
Если нужно переопределить какой-либо метод базового класса в производном классе, то этот метод объявляется в базовом классе как виртуальный. Тогда программы выбирает версию метода, основываясь на типе объекта, а не на типе ссылки или указателя. Виртуальные функции очень полезны когда у вас есть указатель на массив из базовых объектов. Т.е. этот массив может содержать как базовые объекты так и дочерние, соответственно не будет же вызываться для дочернего объекта метод базового класса.
Так же существуют абстрактные классы, в которых без виртуальных функций никуда.
Все это очень хорошо расписано у Праты в 13 главе.