Reputation: 312
I've been looking for a solution to this problem for a while now, and every answer on here has been some variation on not including header files, but I seem to have contracted the dumb and cant figure it out...
I have the base C++ class creature
, that should be implemented in ladybird
and aphid
, but I keep getting expected class-name before ‘{’ token
errors.
creature.h
#ifndef CREATURE_H_
#define CREATURE_H_
#include <iostream>
#include "board.h"
#include "cell.h"
class Creature {
private:
int x, y;
protected:
Creature(int x, int y);
public:
int getX();
int getY();
//virtual bool willMove() = 0;
//virtual void doMove(Board *board) = 0;
//std::ostream& operator<<(std::ostream &out, Creature &cCreature);
};
#endif
aphid.h:
#ifndef APHID_H_
#define APHID_H_
#include "creature.h"
class Aphid : public Creature {
public:
Aphid(int x, int y);
static float moveProbability;
static float killProbabllity;
static float killModifier;
static float matingProbability;
//virtual bool willMove();
//virtual void doMove(Board *board);
};
#endif
ladybird.h:
#ifndef LADYBIRD_H_
#define LADYBIRD_H_
#include "creature.h"
class Ladybird : public Creature {
public:
Ladybird(int x, int y);
static float moveProbability;
static float directionProbability;
static float killProbabllity;
static float matingProbability;
//virtual bool willMove();
//virtual void doMove(Board *board);
};
#endif
Full stack trace
g++ src/*.cpp -o out/main.o -Wall -std=c++11 && ./out/main.o
In file included from src/cell.h:8:0,
from src/board.h:4,
from src/creature.h:5,
from src/aphid.h:4,
from src/aphid.cpp:2:
src/ladybird.h:6:34: error: expected class-name before ‘{’ token
class Ladybird : public Creature {
^
src/cell.cpp: In member function ‘void Cell::simulateMove(Board*)’:
src/cell.cpp:44:19: error: ‘class Aphid’ has no member named ‘willMove’
if((*it)->willMove()){
^
src/cell.cpp:45:18: error: ‘class Aphid’ has no member named ‘doMove’
(*it)->doMove(newBoard);
^
In file included from src/cell.h:7:0,
from src/board.h:4,
from src/creature.h:5,
from src/creature.cpp:1:
src/aphid.h:6:31: error: expected class-name before ‘{’ token
class Aphid : public Creature {
^
In file included from src/cell.h:8:0,
from src/board.h:4,
from src/creature.h:5,
from src/creature.cpp:1:
src/ladybird.h:6:34: error: expected class-name before ‘{’ token
class Ladybird : public Creature {
^
In file included from src/cell.h:7:0,
from src/board.h:4,
from src/creature.h:5,
from src/ladybird.h:4,
from src/ladybird.cpp:2:
src/aphid.h:6:31: error: expected class-name before ‘{’ token
class Aphid : public Creature {
^
I've tried forward declaring the Creature
class, but then I get invalid use of incomplete type ‘class Creature’
board.h:
#ifndef BOARD_H_
#define BOARD_H_
#include "cell.h"
#include "creature.h"
class Board{
private:
Cell ***board; // A 2D ARRAY OF POINTERS, "what if i just add more stars??!" -- Owen G
int width;
int height;
public:
Board(int width, int height);
void populate();
Cell* getCell(int x, int y);
void print();
void simulateMove(Board *board);
};
#endif
cell.h:
#ifndef CELL_H_
#define CELL_H_
#include <iostream>
#include <list>
#include "aphid.h"
#include "ladybird.h"
#include "board.h"
class Board;
class Aphid;
class Ladybird;
class Cell{
private:
int x, y;
std::list<Aphid*> aphids;
std::list<Ladybird*> ladybirds;
public:
Cell(int x, int y);
void addCreature(Aphid *creature);
void addCreature(Ladybird *creature);
int getAphidCount();
int getLadybirdCount();
void simulateMove(Board *nextGenerationBoard);
};
#endif
Upvotes: 1
Views: 71
Reputation: 5118
You have a circular #include dependency in your files.
Let's say you start by including "aphid.h" in some .cpp files, here are the files you are going to include in order:
creature.h (from ladybird.h, skipped because of include guard)
-> ladybird.h will fail to parse because Creature still hasn't been defined when the Ladybird class declaration occurs:
class Ladybird : public Creature { ... };
In order to fix this, you should remove the following lines from the file cell.h:
#include "aphid.h"
#include "ladybird.h"
This compiles fine because the only way you're using these classes within cell.h is by having pointers to them, which does not require complete declarations, and breaks the circular inclusion.
For the same reason, you should probably also remove #include "board.h"
from that file. And while you're at it, you can also remove #include "cell.h"
from the board.h file.
Upvotes: 1
Reputation: 27538
In cell.h, you have:
#include "aphid.h" #include "ladybird.h" #include "board.h" class Board; class Aphid; class Ladybird;
This doesn't make sense. You first include the whole class definitions, then declare the classes again. Just remove the #include
lines:
class Board;
class Aphid;
class Ladybird;
In board.h, you have:
#include "cell.h" #include "creature.h"
And then the following class definition:
class Board{ private: Cell ***board; // A 2D ARRAY OF POINTERS, "what if i just add more stars??!" -- Owen G int width; int height; public: Board(int width, int height); void populate(); Cell* getCell(int x, int y); void print(); void simulateMove(Board *board); };
Creature
is not used anywhere, and Cell
only for pointers. You can safely remove these #include
lines as well and replace them with a forward declaration of Cell
.
By the way: You should get rid of your Cell***
as soon as possible and use std::vector
instead.
Upvotes: 2