When you have a circular include dependency, and you're properly using include guards (as you clearly are), then since there isn't an infinite circular include, the compiler has to stop at some point, and it doesn't know about the contents of the other header. When you add the forward declaration it's able to compile your code.
For example, A
includes B
. Then B
includes A
, but A
' include guard kicks in and prevents it from being evaluated a second time. Then it drops back into B
which doesn't know about anything from A.h
at that point because the include guard prevented its inclusion. The forward declaration however doesn't have any include guards around it so it proceeds as normal.
There's nothing inherently wrong with circular dependencies, but I do always suggest taking a second look at your design to see if factoring out logic into a third class is possible. Forward declarations are the C++ mechanism to prevent infinitely circular dependencies.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…