2015-03-06 2 views
1

Я искал решение этой проблемы какое-то время, и каждый ответ здесь имел некоторые отличия от того, не включая заголовочные файлы, но я, кажется, сократил немые и наклонные понять это ...не может переслать объявление с круговым номером

у меня есть базовый класс C++ 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 класс, но затем я получаю 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 
+0

Вы не можете получить неполный тип - вам нужен этот заголовок. Более того, я не вижу, чтобы какой-либо циркуляр включал в код, который вы опубликовали. – LogicStuff

+1

Насколько возможно, 'cell.h' включает' aphid.h' и 'ladybird.h'? В этом случае, поскольку 'creature.h' включает' cell.h', вы наследуете от Существа до объявления его, и вы не можете перенаправлять объявление класса, на который вы наследуете. – user2313067

+0

@LogicStuff вы ссылаетесь на меня, пытаясь переслать объявление '' Creature'' в '' Aphid'' и '' Ladybird''? – Njdart

ответ

1

У вас есть циклическую зависимость #include в ваших файлах.
Допустим, вы начинаете в том числе «aphid.h» в некоторых файлов .cpp, вот файлы, которые вы собираетесь включить в заказ:

  1. creature.h (определяет включают защитный символ CREATURE_H_)
  2. board.h (от creature.h)
  3. cell.h (от board.h)
  4. aphid.h (от cell.h, пропущена из-за включать в себя охрану)
  5. ladybird.h (от cell.h)
  6. creature.h (от ladybird.h, пропущена из-за включать охрану)

    -> ladybird.h будет не разобрать, потому что существо до сих пор не определено, когда происходит объявление класса божьей коровки:

    class Ladybird : public Creature { ... }; 
    

для того, чтобы исправить это, вы должны удалить следующие строки из файла cell.h:

#include "aphid.h" 
#include "ladybird.h" 

Это компилируется отлично, потому что единственный способ использования этих классов в cell.h состоит в том, что у них есть указатели, которые не требуют полных объявлений и прерывают круговое включение.

По этой же причине, вероятно, вы также должны удалить #include "board.h" из этого файла. И пока вы на нем, вы также можете удалить #include "cell.h" из файла board.h.

+0

Это работает, но кажется интуитивным счетчиком, почему я не должен включать заголовочные файлы в ячейку? – Njdart

+1

Добавление объяснений ... –

+0

Я бы добавил, что «ОК» в этом контексте означает технически возможную, но не обязательно хорошую идею. –

2

В cell.h, у вас есть:

#include "aphid.h" 
#include "ladybird.h" 
#include "board.h" 

class Board; 
class Aphid; 
class Ladybird; 

Это не имеет смысла. Сначала вы включаете определения всего класса, а затем снова объявляете классы. Просто удалите #include линии:

class Board; 
class Aphid; 
class Ladybird; 

В 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); 
}; 

Creature не используется нигде, и Cell только для указателей. Вы также можете безопасно удалить эти линии #include и заменить их на объявление вперед Cell.

К слову: вы должны как можно скорее избавиться от своего Cell*** и использовать вместо этого std::vector.

Смежные вопросы