Virtual isn't just a "placeholder" or "template" and it can (but has not to) be overridden.
In my opinion, the strength of virtual methods is that you can decide which method to use (base, derived) or to define that an specific method has to be implemented by user ( = 0 ). And you can also hide informations from the user.
For example my actual engine iteration has something like this: (pseudo code, does not compile)
class IRenderDevice
{
public:
virtual void Initialise(u16 Width, u16 Height, u8 Bits) = 0;
virtual void Draw(...) = 0;
virtual void Terminate() = 0;
};
class D3D9RenderDevice : public IRenderDevice
{
private:
//some dx9 vars
LPDIRECT3D9* d3d9;
LPDIRECT3DDEVICE9* d3d9device;
public:
virtual void Initialise(u16 Width, u16 Height, u8 Bits);
virtual void Draw(...);
virtual void Terminate();
};
And this is how to use it:
int main(int argc, char** argv)
{
IRenderDevice* mydevice = new D3D9Device();
mydevice->Initialise(800,600,32);
// mainloop
while(true)
{
mydevice->Draw(.....);
}
mydevice->Terminate();
};
So whats the advantage of this ? I just change "new D3D9Device();" with "new OpenGL33Device();" and it uses OpenGL 3.3.
To be honest, this is not the full implementation and style but you should get the idea behind this
In my real code the instances are created by a core class (you can call it factory) and the user of the "engine" has no worries but using directx / opengl by himself. He just uses my interface and classes i provide him.
Of course he could write his own RenderDevice by inheritancing my IRenderDevice and create an instance by himself "new myogrerenderer();" etc.