As I understand, the purpose of making virtual function pure virtual is to force the derived classes to either provide implementation for it or choose the default implementation by explicitly writing Base::f() in the Derived::f().
So if that is true, then what is the purpose of making virtual destructor pure virtual? Does it force the derived classes to provide implementation for Base::~Base()? Can the derived classes implement Base::~Base()? No.
So that means, the first version with virtual destructor seems enough for almost all purposes. After all, the most common purpose of virtual destructor is that the clients can correctly delete objects of the derived classes through pointers of type Base*.
However, if you make all functions in Base virtual only, not pure virtual, and provide implementations for them (actually you've to provide), and at the same time you want to make Base abstract type, then having a pure virtual destructor in Base is the only solution:
class Base
{
public:
virtual void f() {}; //not pure virtual
virtual ~Base() = 0; //pure - makes Base abstract type!
};
Base::~Base() {} //yes, you have to do this as well.
Base *pBase = new Base(); // error - cannot create instance!
Hope that helps.