5

I've been looking at the Fear SDK for my university project, but have noticed some code like so:

Foo.h

class Foo
{
    public:
        int iSomething;
};

Bar.cpp:

#include "Foo.h"

// Forward declarations
class Foo;

Is there any particular reason to forward declare AND include the appropriate header in the same cpp file? Or is the forward declaration redundant because the header is being included?

EDIT:

Every time that I have seen it in the code, the include statement is always before the forward declaration.

Ray Dey
  • 865
  • 2
  • 11
  • 21

4 Answers4

7

It's more than simply redundant, it's potentially problematic. Say Foo.h changes so Foo becomes a typedef to some particular instantiation of a generic, templatised equivalent - the kind of thing that can be anticipated as part of normal software evolution. Then Bar.cpp's "class X" will needlessly cause a compilation error ala:

--- fwd.h ---
template <typename T>
class XT
{
  public:
    int n_;
};

typedef XT<int> X;

--- fwd.cc ---
#include "fwd.h"

class X;

int main()
{
    X x;
    x.n_ = 0;
    return x.n_;
}

--- compilation attempt ---
~/dev  .../gcc/4.1.1/exec/bin/g++ fwd.cc -o fwd
fwd.cc:3: error: using typedef-name 'X' after 'class'
fwd.h:8: error: 'X' has a previous declaration here

This is one reason I always recommend using dedicated forward-declaration headers ala <iosfwd>, maintained with and included by the main header to ensure ongoing consistency. I never put "class X;" in an implementation file unless the class is defined in there too. Remember that the seeming benefits of "class X;" forward declarations is not so much that they avoid an #include, and more that the files they include can be large and in turn include a lot of other files: dedicated forward-declaration headers typically avoid the overwhelming majority of that anyway.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
3

If the forward declaration came before the includes, it might eliminate a dependency. Coming after the actual .h file that defines it does nothing.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Can you elaborate? I originally wrote this exact same thing, but then I thought some more about it and figured that if bar forward-declares Foo, then immediately #includes Foo.h, it should a) always result in the declaration of Foo anyway, and b) never depend upon another header having already declared Foo. Can you give an example where having the forward declaration before the #include actually helps? – mgiuca Feb 08 '11 at 02:04
  • @mgiuca -- reduces compile times. oftentimes code only uses pointers, and never requires the actual size of the class [ and never creates instances ]. In those circumstances, a forward declaration suffices, saving you the time of #include'ing other files. – Foo Bah Feb 08 '11 at 02:15
  • @Foo Bah Yes, that's a good reason to use a forward declaration *instead of* a #include. But it doesn't explain why you'd have both. If you had both, you would need to process the included file, whether it was used or not. – mgiuca Feb 08 '11 at 02:17
  • So if bar.h includes `class Foo;` and foo.h includes `class Bar;` that makes sense. That's a normal cyclic dependency resolved using forward declarations. But I don't see how having the two files subsequently include each other helps. I tried it out, and G++ just went into a loop then bottomed out. If you have cyclic dependency *or* want to improve build times, you replace the `#include` with the forward declaration; it doesn't help (as far as I can tell) to add a FD without removing the `#include`. – mgiuca Feb 08 '11 at 03:04
  • having both headers include each other fails to work -- either you will have an infinite loop of #include's or you put include guards, which means one file effectively ignores the presence of the other. – Foo Bah Feb 08 '11 at 03:31
2

The original class Foo; may have been vestigial.

Remember that, if the source only uses pointers to Foo class [and does not actually try to create Foo objects or dereference Foo pointers], you dont need to define the class before using it.

Without seeing the code, I'd hazard the guess that the original version of bar.cpp had code that did not require the definition of foo

I use forward declarations in large projects to reduce compile time. compile time is not a problem when it takes a second, but when projects take an hour to build every second helps :)

Foo Bah
  • 25,660
  • 5
  • 55
  • 79
1

The forward declaration is redundant, but also quite harmless. Maybe the author uses a lot of forward declarations, and doesn't rigorously ensure they are always required.

Bill Forster
  • 6,137
  • 3
  • 27
  • 27