Итак, мое текущее задание - сделать базовое моделирование Hunter and Prey, и после нескольких других вопросов мой профессор сообщил, что я просто поместил все в main.cpp
, чтобы на самом деле получить вещь, работающая на данный момент.«Недопустимое использование неполного типа» в основных упражнениях Hunter/Prey
Моя текущая проблема заключается в том, что в функции Creature::Find()
она заявляет, что класс Grid
является неполным, хотя он предварительно объявлен в верхней части файла. Моя первоначальная мысль заключалась в том, чтобы поместить класс Grid
до Creature
, но это приводит к гораздо большей или той же ошибке (ссылаясь на Creature
, будучи неполным), поскольку Grid
по существу является двумерным массивом указателей Creature
. Ниже приведены соответствующие биты кода, весь файл можно найти в Dropbox here.
class Grid; //*** error: forward declaration of 'class Grid'
//Other stuff...
class Creature
{
public:
Grid* theGrid;
Coords position;
int stepBreed;
int stepHunger;
char face;
bool hasMoved;
Creature(Grid* _grid, Coords _position, char _face) //Constructor
{
theGrid = _grid;
position = _position;
face = _face;
stepBreed = stepHunger = 0;
hasMoved = false;
}
vector<Coords> Find(char thisFace) //Returns a list of coords with prey on them
{
vector<Coords> result;
for(int i = position.x-1; i <= position.x+1; i++)
for(int j = position.y-1; j <= position.y+1; j++)
{
Coords temp(i,j);
if(theGrid->Occupant(temp) == thisFace) //*** error: invalid use of incomplete type 'class Grid'
result.push_back(temp);
}
return result;
}
virtual Coords Move() = 0; //Allows the creature type to define it's own movement
virtual Coords Breed() = 0; //Allows the creature type to define it's own breeding
virtual bool Starve() = 0; //Allows the creature type to starve of its own accord
};
class Grid
{
public:
Creature* grid[MAX_X][MAX_Y];
Grid() //Initalizes the grid and spawns random creatures
{
cout<<endl<<"grid init"<<endl;
for(int i = 0; i < MAX_X; i++)
for(int j = 0; j < MAX_Y; j++)
grid[i][j] = NULL;
}
void Move() //Tells each creature on the grid to move
{
cout<<endl<<"--- Grid::Move() TOP ---"<<endl<<endl;
ResetMoved();
for(int i = 0; i < MAX_X; i++)
for(int j = 0; j < MAX_Y; j++)
if(grid[i][j])
grid[i][j]->Move();
cout<<endl<<"--- Grid::Move() BOTTOM ---"<<endl<<endl;
}
void Breed() //Tells each creature to breed (if it can)
{
}
void Kill() //Tells each creature to die (if it's old)
{
}
char** Snapshot() //Creates a char array "snapshot" of the board
{
char** result = new char*[MAX_X];
for(int i = 0; i < MAX_X; i++)
{
result[i] = new char[MAX_Y];
for(int j = 0; j < MAX_Y; j++)
{
result[i][j] = Occupant(Coords(i, j));
}
}
return result;
}
Creature* Get(Coords here) //Returns a pointer to the object at the specified position
{
return grid[here.x][here.y];
}
char Occupant(Coords here) //Returns the character of the specified position
{
if(!Get(here))
return FACE_EMPTY;
return Get(here)->face;
}
void Clear(Coords here) //Deletes the object at the specified position
{
cout<<endl<<"--- Grid::Clear() TOP ---"<<endl<<endl;
if(!Get(here))
{
cout<<" inside if"<<endl;
delete Get(here);
}
cout<<" outside if"<<endl;
grid[here.x][here.y] = NULL;
cout<<endl<<"--- Grid::Clear() BOTTOM ---"<<endl<<endl;
}
void ResetMoved()
{
for(int i = 0; i < MAX_X; i++)
for(int j = 0; j < MAX_Y; j++)
if(grid[i][j])
grid[i][j]->hasMoved = false;
}
};
EDIT: Предварительный просмотр и панель инструментов разметки не работает по какой-то причине.
Да, извините, что вы задали новый вопрос по аналогичной теме, не был уверен, оправдал ли он это. Я получал нерешенные внешние функции по различным функциям, и профессор не мог понять, почему и то, поэтому он заставил меня все это выразить в основном. Я думал, что предварительная декларация Grid должна была предотвращать подобные вещи, или это работает только для определений? – Farlo
@Farlo Нет, предварительная декларация (обычно называемая прямым объявлением) сообщает компилятору, что Grid является классом, поэтому (например) 'Grid * theGrid;' является законным. Но передняя декларация не сообщает компилятору ничего о * классе. Таким образом, 'theGrid-> Occupant (temp)' не является законным даже после прямого объявления, потому что в прямом объявлении не сообщается компилятору, что у Grid есть метод под названием Occupant – john
@Farlo. Проблема, которую обычно можно избежать, гарантируя реализацию * * любого кода, который использует неполные типы, следует декларации, которая завершает тип.В этом случае нет ничего, что помешало бы вам переместить реализацию метода «Существо :: Find» вне класса (просто объявите его как член, не реализуйте его в классе) и реализуйте его * после * формального определение 'Grid'. И +1 на ответ. – WhozCraig