rootmeanclaire
rootmeanclaire

Reputation: 838

Enum not recognized even though it is included

I am fairly new to C++, and am having an annoying bug: this previously functional code has stopped working for some reason. Upon compilation the first errors I get are shown below. I think that for some reason it isn't recognizing the enum type Material, even though it is imported.

1>...\chunk.h(10): error C2146: syntax error : missing ';' before identifier 'terrain'
1>...\chunk.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>...\chunk.h(10): error C2065: 'chunkWidth' : undeclared identifier
1>...\chunk.h(10): error C2065: 'chunkWidth' : undeclared identifier
1>...\chunk.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>...\world.h(14): error C2146: syntax error : missing ';' before identifier 'get'
1>...\world.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>...\world.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>...\world.h(14): warning C4183: 'get': missing return type; assumed to be a member function returning 'int'
1>...\world.h(6): error C2011: 'World' : 'class' type redefinition
1>          ...\world.h(6) : see declaration of 'World'
1>...\world.cpp(9): error C2027: use of undefined type 'World'
1>          ...\world.h(6) : see declaration of 'World'

Chunk.h

#pragma once
#include "main.h"

class Chunk {
    private:
        int xpos;
        int ypos;
    public:
        Chunk(int xRelToSpawn, int yRelToSpawn);
        Material terrain[chunkWidth][chunkWidth];
        int getXpos();
        int getYpos();
};

main.h

#pragma once
#include "World.h"

//const int gridSizeX = 30;
//const int gridSizeY = 30;
const int chunkWidth = 15;
const int chunkHeight = 15;
extern int viewportX;
extern int viewportY;
const int viewportWidth = 15;
const int viewportHeight = 15;

enum Material{SAND, WATER};

extern World world = World();

World.h

#include <vector>
#include "main.h"
#include "Chunk.h"
using namespace std;

class World {
    private:
        vector<Chunk> chunks;
    public:
        World();
        ~World();
        bool chunkExists(int x, int y);
        //returns material for absolute coordinates
        Material get(int x, int y);
        //returns world coordinates for given chunk coordinates
        int* getAbsCoords(int chunkIndex, int x, int y);
        int* getChunkCoords(int x, int y);
        Chunk getChunk(int index);
        int getChunkIndex(int x, int y);
        int chunkIndexAbove(int chunkIndex);
        int chunkIndexBelow(int chunkIndex);
        int chunkIndexLeft(int chunkIndex);
        int chunkIndexRight(int chunkIndex);
};

Any help is appreciated.

Upvotes: 1

Views: 10666

Answers (2)

Technophile
Technophile

Reputation: 472

Standard practice for avoiding circular includes is:

  • If you're using a Microsoft compiler, add #pragma once at the start of the file.
  • To work with any compiler, at the start of the .h file:

    #ifndef YOURFILENAME_H

    #define YOURFILENAME_H

    #include "World.h"

    ... body of the .h file ...

    #endif //ndef YOURFILENAME_H

Upvotes: 1

Mooing Duck
Mooing Duck

Reputation: 66922

Somewhere you have

#include "chunk.h"

So the processor stops that file and starts reading chunk.h instead:

#pragma once
#include "main.h"

So the processor starts reading main.h instead:

#pragma once
#include "World.h"

So the processor starts reading World.h instead:

#include <vector>
#include "main.h" //main.h was pragma'd so this is ignored
#include "Chunk.h" //chunk.h was pragma'd so this is ignored
using namespace std;

class World {
    private:
        vector<Chunk> chunks; //here, the compiler should be confused
                              //it hasn't seen what a "Chunk" is yet.

You have circular dependencies. The way to fix this is simple in theory, but tricky in practice. First: Put all of your types/globals/functions in an order:

Material //material needs nothing else to be defined
Chunk //chunk needs material, nothing else to be defined
World //world needs Chunk _and_ material to be defined
extern World world = World(); //needs World to be defined

Then edit your headers so that the data is in this order. Namely, the header containing Material should NOT include the header containing Chunk, World, or world. And the header containing Chunk should NOT include the header containing World or world.

In your case, the types don't have circular dependencies, so this is relatively easy. Move Material to the chunk header (or it's own header) so that the chunk header needs no includes, and nothing needs to include the main header.

Chunk.h //contains Material and Chunk
World.h //contains World
Main.h  //contains extern World world


I don't think that extern World world = World() works in a header. I think you'll have to remove the = World(), and then in a cpp file, put the line:

World world;

This is the actual global variable. The extern in the header merely lets all the other files know that this variable exists somewhere.

Upvotes: 6

Related Questions