3

I have a question about when to use forward declaration vs. include header. I know that there are a lot of questions similar to this out there, but there's just one thing that's a bit confusing.

I've seen the following way in a source code I was looking at:

classA.h

#ifndef H_CLASSA
#define H_CLASSA

class classB;

class classA {
public:
    classA(B* b);
};

and then in classA.cpp:

#include "classA.h"
#include "classB.h" // dependency
classA::classA(B* b) { b->someMethod(); }

In cases like this I've just put #include "class.b" in the classA-header from the start since A has a dependency on class B and uses it. But I don't get why you would forward declare classB first in the header and then include the classB.h in the source file?

Thanks in advance!

user1062704
  • 438
  • 4
  • 14
  • 2
    See this thread (http://stackoverflow.com/questions/3962708/how-much-do-forward-declarations-affect-compile-time) for discussion of advantages of forward declaration from compile times, code readability and avoiding cyclic references. – Luca Jan 18 '15 at 23:47
  • 1
    I can give only one rule: always prefer forward declaration if you can. – SHR Jan 18 '15 at 23:50
  • Yes, but here I would have to include "classB.h" anyway, so would it really be any difference if I included it in the header or source? If classA just needed to know the type and did not call any methods of B, then I would definitely forward declare B instead of including it since that would speed up compilation. – user1062704 Jan 19 '15 at 00:05
  • 2
    It's not about `ClassA`, it's about *the users* of `ClassA`. If you `#include "classB.h"` into `classA.h` then it'll be `#include`d transitively into all files that use `ClassA` but may or may not use `ClassB`. Since you are using `ClassB` in `classA.cpp`, you'll have no choice but need to include it there but you can save your users the burden of the `#include` by keeping the `#include` local to the implementation file and using a forward declaration in `classA.h`. – 5gon12eder Jan 19 '15 at 00:12
  • If you include header in header you include it in any file which include the (last) header, this will cause a bigger pre-processed source files which lead to bigger object files and increase the compilation time, You'll see the differences in large scale systems. when you must (like in heritage, by value arguments etc.) then you got no choice. but when you have the choice use forward declaration. – SHR Jan 19 '15 at 00:17

1 Answers1

1

In order to prevent circular including:

let's say we have the following include path: (each [] is a header file , each -> is include)

[A] -> [B] -> [C]

so far so good. BUT what happens if [A] has some classes or function which takes some objects from [C] as argument? So we can just include (like you said) [C] in [A]. no we can have the following problems : 1) this circular including can cause some errors compiler : first of all , C includes B , B includes A , but A include C! and the cycle continues recursively. 2) lets say [A] has a class A , [B] has a class B that inherits from A and [C] has a class C that inherits from B. let's say the compiler can handle error 1 , still, you'll probably get "Base class not defined" error, since [A] is compiled , before A is compiled all the headers that included ([B] and [C]) are compiled. C is compiled as sub class of A and B , but hey , B and A are not even exist at this point!

this is where forward declarations come handy. it allows me to say "there are 2 classes , B and C , there's still not compiled", and in the cpp file actually uses the header files

but this solution still has some problems . you can only use classes that are forward declared as pointers and references. but , even so, it's extremely recommended to pass objects as reference or const reference . so you can use C and B in [A] , as reference.

David Haim
  • 25,446
  • 3
  • 44
  • 78