Forward declarations have nothing to do with the directory structure of your project. You can forward declare something even not existing in your project. They are mostly used to resolve cyclic references between classes and to speed up compilation when the complete class declaration is not necessary, and the corresponding #include can be replaced with a forward declaration.
To determine when a forward declaration is sufficient, the sizeof() query can usually answer the question. For example,
class Wheel;
class Car
{
Wheel wheels[4];
};
In this declaration, a forward declaration cannot be used since the compiler cannot determine the size of a Car: it doesn't know how much data the wheels contain. In other words, sizeof(Car)
is unknown.
Also regarding templates, forward declared classes cannot be used as template parameters if the template class contains data members of the template parameter (but their pointers can be). For instance,
template<class T> class pointer
{
T *ptr;
};
class Test;
pointer<Test> testpointer;
is legal but
std::vector<Test> testvector
will not compile.
Because of the aforementioned limitations, forward declared classes are generally used as pointers or references.
I don't know if there's a book on the subject but you can see this section on c++ faq lite.