0

This class below is causing a horrendous amount of errors. It appears to be fine though. Any C++ Gurus around who know why VC++ hates me?

Entity.h

#pragma once
#include "World.h"
#include "Renderer.h"

class Entity {
public:
    Entity(World* world, Coordinate coord);
    ~Entity();
    void render(Renderer renderer) const;
    World* world;
    Coordinate coord;
};

Entity.cpp

#include "Entity.h"

Entity::Entity(World* world, Coordinate coord) : world(world), coord(coord) {
    world->entities.insert(this);
}

Entity::~Entity() {
    world->entities.erase(this);
}

The errors themselves don't make a whole lot of sense as they aren't even related to this file. Some of the common errors are unexpected end of file, missing ';' before '{' and "Entity is not a class or namespace name". Those errors do not occur when I do not include Entity in my project. The last of those errors appear in the declaration code of Entity.

The errors (With all duplicates removed): http://pastebin.com/TEMEhVZV

World.h

#pragma once
#include <map>
#include <vector>
#include <unordered_set>
#include "Chunk.h"
#include "Coordinate.h"
#include "Renderer.h"

class World {
public:
    ~World();
    void generateChunk(Coordinate coord);
    void loadChunk(Coordinate coord);
    void renderWorld(Renderer* renderer);
    std::unordered_set<Entity*> entities;
    inline Chunk* getChunk(Coordinate coord) const {
        return loadedChunks.at(coord);
    }
private:
    std::map<Coordinate, Chunk*> loadedChunks;
};

Renderer.h

#pragma once
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include "World.h"

class Renderer {
public:
    sf::Window *window;
    void bind(sf::Window* newWindow);
    void initializeOpenGL();
    void renderChunk(Chunk* chunk);
    inline void drawPoint(Coordinate coord) {
        glBegin(GL_POINTS);
        glVertex3d(coord.x, coord.y, coord.z);
        glEnd();
    }
private:
    template <class T>
    inline static void pushVector3(std::vector<T>* vertices, T x, T y, T z);
};
Jeroen
  • 15,257
  • 12
  • 59
  • 102
  • 6
    without seeing the errors, not much we can do for you – Mgetz Aug 01 '13 at 18:45
  • 1
    World should be a forward declaration rather than an include (unless that's where Coordinate comes from which would be weird). Without seeing the errors (at least show us the first couple), it's going to be really hard to help. – crush Aug 01 '13 at 18:46
  • 2
    sounds like you might be missing some kind of closing character somewhere, like `}` or `;`. That often causes a ridiculous number of errors (commonly "unexpected end of file"), most of which make little to no sense – wlyles Aug 01 '13 at 18:47
  • 2
    Also, VC++ hates left-handed people. That could be the issue. – Alan Aug 01 '13 at 18:48
  • 1
    Are you sure it's not one of the other files causing issues? – Drew McGowen Aug 01 '13 at 18:48
  • 2
    The error is likely in the header you are importing – bengoesboom Aug 01 '13 at 18:48
  • @Mgetz It's kinda ridiculous to post all of them... It'll take you hours to scroll through all of them. – Jeroen Aug 01 '13 at 18:54
  • @Binero take a look at the first one and trace it back from there, as other's have mentioned it's like an issue with one of your header files – Mgetz Aug 01 '13 at 18:56
  • @crush Coordinate.h is included by World.h. Forward declaring World does not fix the errors. – Jeroen Aug 01 '13 at 18:56
  • @bengoesboom Other files were already including both World and Renderer and they had no issue with it. The errors only occur when Entity is added and referenced. – Jeroen Aug 01 '13 at 18:58
  • @tomi.lee.jones Errors are still present. – Jeroen Aug 01 '13 at 18:59
  • @Binero forward declare World and include Coordinate.h manually then. Of course, we STILL don't have your errors, so I can't exactly diagnose your problem with what you've given us. I was just suggesting a better coding practice. Blindly including files just because it's easy will always land you in trouble. – crush Aug 01 '13 at 19:00
  • @Mgetz The other files work fine as long as Entity isn't part of the project. – Jeroen Aug 01 '13 at 19:00
  • @Binero can you please add the contents of `world.h` and `renderer.h` – Mgetz Aug 01 '13 at 19:22
  • @Mgetz Added the additional header files. – Jeroen Aug 01 '13 at 19:44
  • solution is http://stackoverflow.com/questions/625799/resolve-circular-dependencies-in-c – Mgetz Aug 01 '13 at 20:02

3 Answers3

3

To me, it looks like a circular header dependency, meaning something can't be defined.

If your Renderer.h file has a method acting upon an Entity object, and contains this header file as a dependency, Entity will have to be declared before Renderer can be compiled. (The compiler needs to know how big an Entity object will be so it can hard-code the stack offset.)

But similarly, Renderer needs Entity. So it can't be compiled, either!

This may not have shown up in your project before, because the header files are loaded in a different order than now, when the 'Entity' header triggers them.

So, what you should do is modify the headers so there are no circular dependencies, and then reference only pointers in the header, since they have fixed, known sizes. Here are some tricks:

Include low-level classes instead of higher ones.

 #include "World.h" 
 --> 
 #include "Coordinate.h"
 class World;

Use pointers.

#include "Renderer.h" 
void render(Renderer renderer) const;
 --> 
 class Renderer;
 void render(Renderer* renderer) const;

Doing these, the header files can be moved to your .cpp file:

#include "Entity.h"
#include "World.h" 
#include "Renderer.h" 
MST
  • 649
  • 6
  • 4
  • 1
    I agree with this. I think its a circular header dependency as well, which is what I was getting at in the comments. If you only reference a class by pointer in your header file, then you should only forward declare that class, and not include it's header file. – crush Aug 01 '13 at 19:26
  • Shouldn't #pragma once fix this though? Or am I being a total noob and totally misunderstood the point? – Jeroen Aug 01 '13 at 19:46
  • Well.. the point is mainly to have headers include as few other headers as possible. Another problem could be that you never included a certain class def in another header file, but due to the differing order they were compiled in, the dependent class was always defined by this point. Say class 'a' includes 'b' and 'c', and 'b' uses 'c'. – MST Aug 01 '13 at 20:25
  • In terms of headers: say class A includes B and C, and C uses (but does not include) B. Next, we include class D in class A, and class D includes C. If, in file A, we include D before B and C, C is examined before B is defined, C will be incomplete, and compilation will fail for every file using D as a header. Many errors will be thrown. So there may also be an external class that is relying on something else being defined. 'Pragma once' doesn't guard against errors like this, but it does make the order the headers are examined in, arbitrary. – MST Aug 01 '13 at 20:35
0

It's hard to give too much help without more context. In my experience, errors like this almost always relate to a missing semicolon. Are you given a file and line number with those errors? I would check in Renderer.h, and make sure it is not missing a semicolon.

The reason I suggest this is because, when you #include a file, the compiler actually copies it in to this file. That means that typos in previous files can manifest themselves in these files. If you can post more information, or even copy and paste the errors themselves, I'll try to be more helpful.

EDIT: Since you've posted your errors, this makes much more sense. If you look, the first error in the list is actually number 148. You have to scroll down for error number 1:

"Error 1 error C2065: 'Entity' : undeclared identifier world.h"

To me, this looks like you're trying to use the class Entity in the file world.h, and it doesn't exist yet. So this looks like a circular include problem.

TylerLubeck
  • 608
  • 4
  • 6
  • The errors only occur when these 2 files are included into the project and referenced. – Jeroen Aug 01 '13 at 18:55
  • Shouldn't #pragma once fix that? – Jeroen Aug 01 '13 at 19:51
  • 1
    #pragma once only ensure that the file is included once. It does not ensure that they're included in the right order. It looks as though you're trying to use an item before it is defined, among other things. – TylerLubeck Aug 01 '13 at 19:54
  • 1
    @Binero sort of `#pragma once` only means to include the file once, the problem with that and the cause of the issue here is that you need to provide a forward declaration in each header of the other class. This is because when included in entity it causes only one of them to be included in the right order. – Mgetz Aug 01 '13 at 19:54
  • @Mgetz Shouldn't an include guard fix this then? Or are all include tags parsed before the if statements by the preprocessor? – Jeroen Aug 01 '13 at 19:58
  • @Binero `#include` statements are actually part of the preprocessor so they are executed in order. Headers are not like Java and C# you need to forward declare the classes in the other file `class Renderer;` etc. – Mgetz Aug 01 '13 at 20:01
  • @Mgetz Worked. If you add it as an answer I'll accept it. – Jeroen Aug 01 '13 at 20:24
  • @Binero can't question is on hold, also technically a duplicate of the link I posted in my last comment on the original question – Mgetz Aug 01 '13 at 20:33
0

Try going to the very first error its spits out, and fixing that one. In VC++ double-clicking there should take you to the line in question. Often times after the first error or two the compiler is so hopelessly confused that nothing else in its output is worth looking at.

My suspicion would be that it will take you to a line in one of those header files you are not displaying.

T.E.D.
  • 44,016
  • 10
  • 73
  • 134
  • The first error simply says "C1003: error count exceeds 100; stopping compilation". All errors behind that make completely no sense. – Jeroen Aug 01 '13 at 18:57