2

For a C++-project, I need to make a game with Doodlebugs and Ants, which are both Organisms. So, I made a class called Organism with the following definition (although I'll probably add way more member functions and member variables, of course).

Organism.h:

#ifndef ORGANISM_H
#define ORGANISM_H

#include "World.h"

class Organism
{
    public:
        Organism();
        ~Organism();    

        virtual void Move() = 0;

        friend class World;

        int survivalTime;
};

#endif

Organisms live in 'the World', which is a class with (among others) a member variable Organism*** field, a two-dimensional dynamic array containing pointers to Organism objects.

World.h:

#ifndef WORLD_H
#define WORLD_H

#include "Organism.h"
#include "Ant.h"
#include "Doodlebug.h"

class World
{
    public:
        World();
        ~World();

        void gameplay();

        Organism*** field;
};

#endif

You probably already guessed it: Ant and Doodlebug are derived from Organism.

Ant.h:

#ifndef ANT_H
#define ANT_H

#include "Organism.h"

class Ant : public Organism
{
    public:
        Ant();
        ~Ant();
        void Move();
};

#endif

Doodlebug.h:

#ifndef DOODLEBUG_H
#define DOODLEBUG_H

#include "Organism.h"

class Doodlebug : public Organism
{
    public:
        Doodlebug();
        ~Doodlebug();
        void Move();
};

#endif

As you can see, Ant.h and Doodlebug.h are almost identical, except for the words Doodlebug and Ant. However, I have two errors.

  1. In World.h, line 16: "'Organism' does not name a type."
  2. In Doodlebug.h, line 7: "expected class-name before '{' token"

Why is this? The first error can be solved by putting class Organism; right before the definition of class World, but I don't understand why that changes anything, since the complete definition of Organism is in Organism.h, which I include.

The second error is the one I'm VERY confused by (and kind of the main reason I'm asking this question), since Ant.h is identical to Doodlebug.h except for the words Ant and Doodlebug, but in Doodlebug.h I get an error but not in Ant.h???

Any help is greatly appreciated.

  • `Organism` needs a virtual destructor. – Christian Hackl Jul 28 '15 at 19:19
  • `Organism.h` now does not include any files. `World.h` now only includes `Ant.h` and `Doodlebug.h` which include `Organism.h`. Fortunately, `Organism.h` does NOT need to know anything about `World` since `friend class World` does not require the definition of `World`. So no forward declarations needed. –  Jul 28 '15 at 22:15

4 Answers4

3

You have circular dependency between World.h and Organism.h.

World.h has

#include "Organism.h"

and Organism.h has

#include "World.h"

You can remove the above line from Organism.h and replace it with a forward declaration.

class World;

Use forward declaration in header files if you don't need the definition of a as a matter of principle. That will not only avoid problems like the one you encountered but it will also reduce compile time dependecies.

Additional references:

Forward declaration vs include
When can I use a forward declaration?

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    I would add that one should use forward declarations whenever it's possible. It allows to avoid most of problems like the given above. – bartop Jul 28 '15 at 16:51
  • 1
    Forward declarations also improve compilation speed, possibly _a lot_. – Kamajii Jul 30 '15 at 15:50
2

You did not post your compile command (and most importantly what is the file you try to compile?), but below is what I think your problem is.

The main problem is that your Organism.h includes World.h, which in turn tries to include Organism.h once again, but does not actually include it due to include guards. Therefore, in World.h the compiler still does not know what Organism is and thus generates the first error. You can use forward declaration to solve this: just write

class Organism;

in World.h before class World...; you can also remove #include "Organism.h" from World.h.

I suppose that your second problem can be related to this also.

Note that you can use -E parameter to g++ to generate the file as compiler sees it after preprocessing. Very useful to catch these include-related problems.

Petr
  • 9,812
  • 1
  • 28
  • 52
0

The first issue derives from your include "mess". When Organism.h is processed (maybe because a corresponding Organism.cc is compiled) the include statement is replaced by the actual contents, i.e. it is replaced by the contents of World.h. That effectively yields a translation unit where the declaration of World stands before the declaration of Organism, hence leading to the error.

Kamajii
  • 1,826
  • 9
  • 21
  • So in `Organism.h`, before `#include "World.h"`, I put a forward declaration, `class Organism`. In `World.h`, I still write `#include "Organism.h"`, because it will not be defined a second time. I now see why this solves the problem. I didn't realize that `#include` statements basically (or actually) copy the code to the place of the `#include` statement. –  Jul 28 '15 at 17:18
  • Simply do not include `World.h` in `Organism.h` at all. Just forward-declare `class World;`, that will suffice. And as well don't include `Organism.h` in `World.h`, put a forward declaration for `class Organism;` there instead. – Kamajii Jul 30 '15 at 15:47
  • Yes indeed, `#include` statements _are_ actually copy-and-paste instructions to the preprocessor, literally. – Kamajii Jul 30 '15 at 15:49
0

You could also probably remove #include "Organism.h" from your World.h as you have included that in both your Ant and Doodlebug classes, and both of those are included in your World class.

Tyler
  • 197
  • 3
  • 13