Я пытаюсь скомпилировать несколько файлов для агентского моделирования зомби-апокалипсиса (Удивительно, верно !?). В любом случае, я получаю сообщение об ошибке, касающееся порядка включения заголовочных файлов, но я не могу обернуть голову, как выяснить, что идет не так и как это исправить. Точная ошибка: «В файле, включенном в main.cpp, поле« Местоположение »имеет неполный тип». Затем аналогичным образом, «В конструкторе Creature :: Creature () ‘Location’ undeclared».
Вот мои файлы:
definitions.h
#ifndef definitions_h
#define definitions_h
class Creature;
class Item;
class Coords;
class Grid
{
public:
Creature*** cboard;
Item*** iboard;
Grid(int WIDTH, int HEIGHT);
void FillGrid(int H, int Z); //initializes grid object with humans and zombies
void Refresh(); //calls Creature::Die(),Move(),Attack(),Breed() on every square
void UpdateBuffer(char** buffer);
bool isEmpty(int startx, int starty, int dir);
};
class Random
{
public:
int* rptr;
void Print();
Random(int MIN, int MAX, int LEN);
~Random();
private:
bool alreadyused(int checkthis, int len, int* rptr);
bool isClean();
int len;
};
class Creature
{
public:
bool alive;
Coords Location;
char displayletter;
Creature() {Location.x=0; Location.y=0;} //ERROR HERE
Creature(int i, int j) {Location.xvalue(i); Location.yvalue(j);}
virtual void Attack();
virtual void Breed();
virtual void Move(Creature*** cboard);
virtual void Die();
virtual void MoveTo(Creature*** cboard, int dir);
virtual int DecideSquare(Creature*** cboard);
};
class Human : public Creature
{
public:
bool armed; //if armed, chances of winning fight increased for next fight
bool vaccinated; //if vaccinated, no chance of getting infected
int bitecount; //if a human is bitten, bite count is set to a random number
int breedcount; //if a human goes x steps without combat, will breed if next to a human
int starvecount; //if a human does not eat in x steps, will die
void Attack(Creature*** cboard);
void Breed(Creature*** cboard); //will breed after x steps and next to human
void Move(Creature*** cboard); //moves and checks itemboard for food
void Die(); //depends on bitecount, starvecount, and bool alive
void MoveTo(Creature*** cboard, int dir);
int DecideSquare(Creature*** cboard) {Creature::DecideSquare(Creature*** cboard);}
};
class Zombie : public Creature
{
public:
Zombie(int i, int j) {Creature::Creature()};
void Attack(Creature*** cboard); //will attack any adjacent human
void Breed() {} //does nothing
void Move(Creature*** cboard) {Creature::Move(Creature*** cboard;}
void Die(); //can only die from being attacked, never starves};
class Item
{
};
class Coords
{
public:
int x;
int y;
int MaxX;
int MaxY;
Coords() {x=0; y=0; MaxX=0; MaxY=0;}
Coords(int X, int Y, int WIDTH, int HEIGHT) {x=X; y=Y; MaxX=WIDTH; MaxY=HEIGHT; }
void MoveRight();
void MoveLeft();
void MoveUp();
void MoveDown();
void MoveUpRight();
void MoveUpLeft();
void MoveDownRight();
void MoveDownLeft();
void MoveDir(int dir);
void setx(int X) {x=X;}
void sety(int Y) {y=Y;}
};
#endif
main.cpp
#include <cstdlib>
#include <iostream>
#include "definitions.h"
using namespace std;
int main(int argc, char *argv[])
{
system("PAUSE");
return EXIT_SUCCESS;
}
definitions.cpp
#include <cstdlib>
#include "definitions.h"
Grid::Grid(int WIDTH, int HEIGHT)
{
//builds 2d array of creature pointers
cboard = new Creature**[WIDTH];
for(int i=0; i<WIDTH; i++)
{
cboard[i] = new Creature*[HEIGHT];
}
//builds 2d array of item pointers
iboard = new Item**[WIDTH];
for (int i=0; i<WIDTH; i++)
{
iboard[i] = new Item*[HEIGHT];
}
}
void Grid::FillGrid()
{
/* For each creature pointer in grid, randomly selects whether to initalize
as zombie, human, or empty square. This methodology can be changed to initialize
different creature types with different probabilities */
int random;
for (int i=0; i<WIDTH; i++)
{
for (int j=0; j<HEIGHT; j++)
{
Random X(1,100,1); //create a single random integer from [1,100] at X.rptr
random=X->rptr;
if (random < 20)
cboard[i][j] = new Human(i,j);
else if (random < 40)
cboard[i][j] = new Zombie(i,j);
else
cboard[i][j] = NULL;
}
} //at this point every creature pointer should be pointing to either
//a zombie, human, or NULL with varying probabilities
}
void Grid::UpdateBuffer(char** buffer)
{
for (int i=0; i<WIDTH; i++)
{
for (int j=0; j<HEIGHT; j++)
{
if (cboard[i][j])
buffer[i][j]=cboard[i][j]->displayletter;
else
buffer[i][j]=' ';
}
}
}
bool Grid::isEmpty(int startx, int starty, int dir)
{
Coords StartLocation(startx,starty,WIDTH,HEIGHT);
switch(dir)
{
case 1:
StartLocation.MoveUp();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 2:
StartLocation.MoveUpRight();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 3:
StartLocation.MoveRight();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 4:
StartLocation.MoveDownRight();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 5:
StartLocation.MoveDown();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 6:
StartLocation.MoveDownLeft();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 7:
StartLocation.MoveLeft();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 8:
StartLocation.MoveUpLeft();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
}
return 1;
}void Coords::MoveRight() {(x==MaxX)? (x=0):(x++);}
void Coords::MoveLeft() {(x==0)? (x=MaxX):(x--);}
void Coords::MoveUp() {(y==0)? (y=MaxY):(y--);}
void Coords::MoveDown() {(y==MaxY)? (y=0):(y++);}
void Coords::MoveUpRight() {MoveUp(); MoveRight();}
void Coords::MoveUpLeft() {MoveUp(); MoveLeft();}
void Coords::MoveDownRight() {MoveDown(); MoveRight();}
void Coords::MoveDownLeft() {MoveDown(); MoveLeft();}
void Coords::MoveDir(int dir)
{
switch(dir)
{
case 1:
MoveUp();
break;
case 2:
MoveUpRight();
break;
case 3:
MoveRight();
break;
case 4:
MoveDownRight();
break;
case 5:
MoveDown();
break;
case 6:
MoveDownLeft();
break;
case 7:
MoveLeft();
break;
case 8:
MoveUpLeft();
break;
case 0:
break;
}
}
Когда переменная объявлена, ее тип должен быть известен. В вашем случае это означает определение Coords
должно предшествовать его использованию в объявлении Coords Location;
,
Посмотрите на это с точки зрения компилятора: нужно знать, сколько места Location
возьмет, и для этого нужно знать определение Coords
, И конечно, это разбор сверху вниз.
Ваша предварительная декларация class Coords
в definitions.h
недостаточно объявить переменную типа Coords
,
Форвардное объявление вводит тип, но оставляет его неполным. Вы можете объявить переменную с указателем на неполный тип, но не переменную с неполным типом. Таким образом, вы должны переместить определение class Coords
до определения class Creature
,
Если вы обнаружите циклическую зависимость объявления, вы должны ввести указатель или ссылочный декларатор для ее решения.