1

I have few different classes. Few pairs need to know about each other. To prevent the headache I've created one file to keep forward declarations of all troublesome classes along with proper include order.

#ifndef GLPROJECT_H
#define GLPROJECT_H

class MainWindow;
class Scene;
class ShaderProgram;
class Shape;

#include "ShaderProgram.h"
#include "MainWindow.h"
#include "Shape.h"
#include "Scene.h"

#endif

Every file who needs another one from the given set include this header. I came up with an idea to put all includes inside include guard, so for example Shape.h class looks like:

#ifndef SHAPE_H
#define SHAPE_H

#include "GLProject.h" //file above

//...class definition code

#endif

However this example produces error: field ‘x’ has incomplete type ‘GLProject::Shape’ in file Scene.h, which is stated after the Shape.h in the main header (other files don't include Scene.h explicitly).

(Note that following flow is correct only for files which directly include GLProject.h) If I'd trace the inclusion of files starting with GLProject.h, then: 1)

  1. it includes the first header which doesn't include any of these headers,
  2. MainWindow which include GLProject.h but it's completely omited due to include guards,
  3. Shape.h which defines Shape.h (after trying to include guarded GLProject.h)
  4. Scene.h which declares viariable of type Shape that should be already defined.

So no idea why does it complains that Shape is incomplete type.

What's more interesting moving inclusion of file GLProject.h in file Shape.h above include guards fixes the problem. (the most important fact)

pkubik
  • 780
  • 6
  • 19
  • 1
    That *specific* example produces no such error, at least not for *us*. There is no field `x` in any of this code, much less one declared to be a type that is unfinished. Any `Shape` that is not a reference or pointer var occurring in `MainWindow.h`, `ShaderProgram.h`, or *anything they pull in* is incomplete until *after* `Shape.h` has been included (one way or another); not before. I'd check your include-guards to make sure each file has *unique* macros. – WhozCraig Jul 18 '14 at 21:10
  • 1
    Have you looked at the preprocessor output? – Khouri Giordano Jul 18 '14 at 21:11
  • Putting all of the `#include` statements into a single file is not the same thing as creating proper forward declarations. `GLProject.h` makes sense as a procompiled header as a compiler optimization, but it does not solve the problem of referencing classes that have not been declared yet. You still need proper forward declarations for that. – Remy Lebeau Jul 18 '14 at 21:17
  • Well, apparently your analysis of how these files are included is incorrect. I'd guess that `Shape.h` somehow somewhere gets included directly, without going through `GLProject.h`. That causes the `GLProject.h` inclusion to get actually expanded in `Shape.h` (since there's no guard for `GLProject.h` yet), skip inclusion of `Shape.h` (since it is already guarded) and then include and expand `Scene.h`. The latter fails to compile. – AnT stands with Russia Jul 18 '14 at 23:28

1 Answers1

1

Ok. The actual problem was connected with not mentioned file Shape.cpp which of course included Shape.h and the fact that moving #include "GLProject.h" before the guard were fixing the problem. The flow with the include directive inside the guard:

Shape.h (def guard)
     GProject.h (def guard) 
          ...(MainWindow.h and ShaderProgram.h)...//not interesting

          Shape.h (omit, because of guard)

          Scene.h
                GProject.h (omit, because of guard)
          back to Scene.h (def guard) ERROR

While with the directive outside:

Shape.h
     GProject.h (def guard)
          ...(MainWindow.h and ShaderProgram.h)...//not interesting

          Shape.h
                GProject.h (omit, cause of guard)
          back to Shape.h (now def guard and class)

          Scene.h
                GProject.h (omit, because of guard)
          back to Scene.h (def guard) No error - Shape defined
pkubik
  • 780
  • 6
  • 19