A forward declaration can always be used, when the compiler only needs to know that some object exists, but doesn't need it's size or other details iof the object.
For example in some .h file you have:
MyClass *foo(MyClass *p);
In example1.cpp:
// No include needed, forward declaration is ok.
MyClass *foo(MyClass *p)
{
foo2(p);
return p;
}
In example2.cpp:
// include needed, forward declaration is not ok.
MyClass *foo(MyClass *p)
{
p->ClassFkt();
return p;
}
In example3.cpp:
// include needed, forward declaration is not ok.
MyClass *foo(MyClass *p)
{
MyClass *n = new MyClass();
foo2(p, n);
return n;
}
Here you have a prototype of a function which takes a pointer. A pointer is always of known size, so a forward declaration can be used here.
As long as you only use the pointer, for example to pass it on, to some other function, you don't need the include. If you try to access some members or do other operation which requires to know more details, you need to include the header file as well. In the above example1 you wouldn't need the full declaration and the forward declaration is sufficient. In the secaond example it is not, because the compiler doesn't know if your class has the function which is invoked. In the third example only pointers are used, but because of the new
the size needs to be known, so a forward declaration is not enough.
In order to avoid extra header depencies, you can use the forward declaration in the .h
file in the above example, and do the include only in the cpp file itself.