Consider this classic example used to explain what not to do with forward declarations:
//in Handle.h file
class Body;
class Handle
{
public:
Calling a virtual method or a non-virtual method are two totally different things.
If you call a non-virtual method, the compiler has to generate code that does this:
Since we're talking about the destructor, there are no arguments to put on the stack, so it looks like we can simply do the call and tell the linker to resolve the call. No prototype needed.
However, calling a virtual method is totally different:
This is totally different so the compiler really has to know whether you are calling a virtual or non-virtual method.
The second important thing is that the compiler needs to know on which position the virtual method is found in the vtable. For this, it also needs to have the full definition of the class.