1

Why do I need to use forward declarations for a class when I am already including the relevant header file? It has fixed my problem but confused me!

essentially class A needs to know about class B and visa-versa. I was getting the error "sytax error - identifier" before I included the forward declarations. I was under the impression including a header file essentially meant you WERE declaring the other class where you put #include.

Dollarslice
  • 9,917
  • 22
  • 59
  • 87

3 Answers3

5

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.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • quite simply I have three types of collision object, a box, a sphere and a ray. each one includes the others so it can have an overloaded version of its Intersects() function that takes one of the other objects as a parameter. Do you think there is a better way of doing this or is the circular includes with the forward declarations ok? – Dollarslice Oct 13 '11 at 17:00
  • 1
    @SirYakalot: Have you considered providing free functions that perform the collision detection? Those functions depend on the three shapes, but the shapes don't really care about any other shape in the system. – David Rodríguez - dribeas Oct 13 '11 at 17:10
  • 1
    You're trying to solve [double dispatch](http://en.wikipedia.org/wiki/Double_dispatch) using method overloading, and the article linked describes the problem with that. In general, having all subclasses know about each other, and implementing both `box+sphere` and `sphere+box` collisions as if they were different, will scale poorly. I'll see if I can dig up a decent reference for implementing multiple dispatch in C++ ... – Useless Oct 13 '11 at 17:23
  • Actually, @SirYakalot - that might make a good question in itself, so go ask that. – Useless Oct 13 '11 at 17:24
3

If you have a circular declaration dependence, you'll probably have something like this:

  • A.h defined class A and starts with #include "B.h"

  • B.h defined class B and starts with #include "A.h"

Now, your header files will have include guards, so they're only included once. So in the context of B.h, there's only a single inclusion of A.h, so you'll get something that's effectively like this:

class A { B * bp; };  // from `#include "A.h"`

class B { A * ap; };

Now you're stuck, because the first line is incorrect without having the declaration of B. You fix this by adding a forward declaration to A.h:

// A.h
#ifndef H_A
#define H_A

class B;
class A { B * bp; };

#endif
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

A viceversa relation between classes always needs at least one forward declaration. You can define only a class at a time, so when you define the first class the second is undefined so far. Including headers is not enough, because those headers should also be including each others. Including a file is no different than pasting its contents at the include location. With that in mind, how would you declare two classes that refer to each other within a single file? The answer, as you already know, is forward declarations.

K-ballo
  • 80,396
  • 20
  • 159
  • 169