不能用通告包含转发声明
cannot forward declare with circular includes
我一直在寻找这个问题的解决方案,这里的每一个答案都有一些关于不包括头文件的变体,但我似乎已经被愚弄了,无法弄清楚。 ..
我有基本的 C++ class creature
,应该在 ladybird
和 aphid
中实现,但我不断收到 expected class-name before ‘{’ token
错误。
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
完整堆栈跟踪
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 {
^
我已经尝试向前声明 Creature
class,但后来我得到 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
您的文件中有循环 #include 依赖项。
假设您首先在一些 .cpp 文件中包含 "aphid.h",以下是您要按顺序包含的文件:
- creature.h(定义包含保护符号CREATURE_H_)
- board.h(来自creature.h)
- cell.h(来自board.h)
- aphid.h(来自 cell.h,因为包含保护而跳过)
- ladybird.h(来自cell.h)
creature.h(来自 ladybird.h, 因包含防护 而跳过)
-> ladybird.h 将无法解析,因为当 Ladybird class 声明发生时 Creature 仍未定义:
class Ladybird : public Creature { ... };
为了解决这个问题,您应该从文件 cell.h 中删除以下行:
#include "aphid.h"
#include "ladybird.h"
这可以很好地编译,因为您在 cell.h 中使用这些 classes 的唯一方法是使用指向它们的指针,这不需要完整的声明,并且会破坏循环包含。
出于同样的原因,您可能还应该从该文件中删除 #include "board.h"
。当你这样做时,你还可以从 board.h 文件中删除 #include "cell.h"
。
在 cell.h 中,您有:
#include "aphid.h"
#include "ladybird.h"
#include "board.h"
class Board;
class Aphid;
class Ladybird;
这没有意义。您首先包含整个 class 定义,然后再次声明 classes。只需删除 #include
行:
class Board;
class Aphid;
class Ladybird;
在 board.h 中,您有:
#include "cell.h"
#include "creature.h"
然后是下面的class定义:
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
不在任何地方使用,Cell
仅用于指针。您也可以安全地删除这些 #include
行,并用 Cell
.
的前向声明替换它们
顺便说一句:你应该尽快摆脱你的 Cell***
并改用 std::vector
。
我一直在寻找这个问题的解决方案,这里的每一个答案都有一些关于不包括头文件的变体,但我似乎已经被愚弄了,无法弄清楚。 ..
我有基本的 C++ class creature
,应该在 ladybird
和 aphid
中实现,但我不断收到 expected class-name before ‘{’ token
错误。
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
完整堆栈跟踪
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 {
^
我已经尝试向前声明 Creature
class,但后来我得到 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
您的文件中有循环 #include 依赖项。
假设您首先在一些 .cpp 文件中包含 "aphid.h",以下是您要按顺序包含的文件:
- creature.h(定义包含保护符号CREATURE_H_)
- board.h(来自creature.h)
- cell.h(来自board.h)
- aphid.h(来自 cell.h,因为包含保护而跳过)
- ladybird.h(来自cell.h)
creature.h(来自 ladybird.h, 因包含防护 而跳过)
-> ladybird.h 将无法解析,因为当 Ladybird class 声明发生时 Creature 仍未定义:
class Ladybird : public Creature { ... };
为了解决这个问题,您应该从文件 cell.h 中删除以下行:
#include "aphid.h"
#include "ladybird.h"
这可以很好地编译,因为您在 cell.h 中使用这些 classes 的唯一方法是使用指向它们的指针,这不需要完整的声明,并且会破坏循环包含。
出于同样的原因,您可能还应该从该文件中删除 #include "board.h"
。当你这样做时,你还可以从 board.h 文件中删除 #include "cell.h"
。
在 cell.h 中,您有:
#include "aphid.h" #include "ladybird.h" #include "board.h" class Board; class Aphid; class Ladybird;
这没有意义。您首先包含整个 class 定义,然后再次声明 classes。只需删除 #include
行:
class Board;
class Aphid;
class Ladybird;
在 board.h 中,您有:
#include "cell.h" #include "creature.h"
然后是下面的class定义:
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
不在任何地方使用,Cell
仅用于指针。您也可以安全地删除这些 #include
行,并用 Cell
.
顺便说一句:你应该尽快摆脱你的 Cell***
并改用 std::vector
。