Consider this classic example used to explain what not to do with forward declarations:
//in Handle.h file
class Body;
class Handle
{
public:
I'm just guessing, but perhaps it has to do with the ability of per-class allocation operators.
That is:
struct foo
{
void* operator new(size_t);
void operator delete(void*);
};
// in another header, like your example
struct foo;
struct bar
{
bar();
~bar() { delete myFoo; }
foo* myFoo;
};
// in translation unit
#include "bar.h"
#include "foo.h"
bar::bar() :
myFoo(new foo) // uses foo::operator new
{}
// but destructor uses global...!!
And now we've mismatched the allocation operators, and entered undefined behavior. The only way to guarantee that can't happen is to say "make the type complete". Otherwise, it's impossible to ensure.