Мне не нравится публиковать что-то настолько тонкое, но это меня полностью задевает на то, что я делаю неправильно: когда я компилирую, мне не нравится Simulator классов. Я получаю ошибку
syntax error : identifier 'Simulator'
в каждом экземпляре Simulator я использую внутри файла заголовка DOCO. Он также делает это для моей структуры Pellet. Код работал полностью нормально, пока я не начал добавлять функции, которые работают с классом Simulator внутри DOCO.h. Класс Simulator использует структуру DOCO, а структура DOCO использует класс Simulator. Это проблема? Может быть, я использовал в своих заголовках неправильно?
Вот ссылка на ошибку, которую я получаю, если она помогает: http://msdn.microsoft.com/en-us/library/yha416c7.aspx
#include <iostream>
#include <conio.h>
#include <string>
#include "Simulator.h" //<---Has a chain of includes for other header files
int main()
{
RandomNumberGen R;
Simulator S;
Pellet P;
DOCO D;
system("pause");
return 0;
}
Файлы заголовков: Simulator.h
#pragma once
#include <iostream>
#include <stdio.h>
//#include <conio.h>
#include <vector>
#include "Pellet.h"
#include "DataParser.h"
#include "DOCO.h"
#include "RandomNumberGen.h"
#include "Cell.h"
#include "Timer.h"
using namespace std;
class Simulator
{
private:
int s_iDocoTotal;
int s_iPelletTotal;
int s_iGridXComponent;
int s_iGridYComponent;
int tempX;
int tempY;
//Pellet P;
//DOCO D;
static const unsigned int s_iNumOfDir=8;
public:
Simulator();
~Simulator();
//int GenerateDirection();
void InitiateDOCO(RandomNumberGen *R, DOCO *D, vector<DOCO>&); //
void SpreadFood(RandomNumberGen *R, Pellet *P, vector<Pellet>&, const int x, const int y); //
void AddPellet(Pellet *P, RandomNumberGen *R); //
void CheckClipping(Pellet *P, RandomNumberGen *R); //
void CheckPellets(Pellet *P, RandomNumberGen *R); //
void CreateGrid(int x, int y);//
int GetGridXComponent(); //
int GetGridYComponent(); //
int GetDocoTotal();
vector<DOCO> docoList; //Holds the Doco coordinates
vector<Pellet> pelletList; //!!Dont use this!! For data import only
vector<vector<int> > pelletGrid; //Holds X-Y and pellet count
char **dataGrid; //Actual array that shows where units are
Simulator(const int x, const int y) :
s_iGridXComponent(x),
s_iGridYComponent(y),
pelletGrid(x, vector<int>(y)){}
};
DOCO.h
#pragma once
#include <iostream>
#include <stdio.h>
#include <vector>
#include "Simulator.h"
//#include "DataParser.h"
using namespace std;
struct DOCO
{
private:
int d_iXLocation;
int d_iYLocation;
int d_iEnergy;
int d_iMovement;
int d_iTemp;
//Simulator S;
//RandomNumberGen R;
//Pellet P;
enum Direction { NORTH, SOUTH, EAST, WEST, NORTHWEST, NORTHEAST, SOUTHWEST, SOUTHEAST};
public:
DOCO();
~DOCO();
//int a is the position in docoList to reference DOCO
int GoNorth(Simulator *S, int a);
int GoSouth(Simulator *S, int a);
int GoEast(Simulator *S, int a);
int GoWest(Simulator *S, int a);
int GoNorthWest(Simulator *S, int a);
int GoNorthEast(Simulator *S, int a);
int GoSouthWest(Simulator *S, int a);
int GoSouthEast(Simulator *S, int a);
//int a is the position in docoList to reference DOCO
void Sniff(Simulator *S, RandomNumberGen *R, int a); //Detects DOCOs and food
void Reroute(Simulator *S, RandomNumberGen *R, int a); //Changes DOCO direction
void SetDOCO(int tempX, int tempY, int tempEnergy, int tempMovement);
int GetEnergy(); //
int SetEnergy();
int SetMovement();
int GetMovement(); //
int GetXLocation(); //
int GetYLocation(); //
void SetXLocation(int d_iTemp);
void SetYLocation(int d_iTemp);
void EatPellet(Pellet *P, Simulator *S, int a);//ADD DOCO ARGUMENT / DONT OVERLAP DOCO AND PELLETS
void MoveDoco(Simulator *S, int a);
void Death();
};
Как я уже говорил выше, ваша проблема связана с рекурсивным включением.
Вы можете сделать одну из двух вещей:
1) Измените свой симулятор, чтобы вы использовали ссылки на DOCO или указатели на DOCO и, таким образом, forward declare
DOCO.
2) Измените свой заголовок DOCO, чтобы использовать указатели на Simulator или ссылки на Simulator, а затем просто перейдите на объявление Simulator
.
Самый простой для изменения (если эти комментарии в вашем коде остаются) заключается в изменении DOCO.h
:
#pragma once
#include <iostream>
#include <stdio.h>
#include <vector>
class Simulator;
struct DOCO
{
...
};
Внутри определения структуры DOCO
вы можете указать ссылки и указатели на Simulator
, а не на объекты Simulator.
Я также советую не ставить using namespace std;
в файле заголовка. Это обсуждается во многих потоках здесь, на SO о том, почему вы не должны иметь эту строку в своем файле заголовка.
using namespace std;
в заголовках это зло, хорошая мысль.
После того, как #includes в файле Simulator.h
добавьте строку
struct DOCO;
После # Doco.h
файл Doco.h
добавьте строку
class Simulator;
Это говорит вашему компилятору, что, хотя при компиляции файла Simulator он еще не знает, что такое DOCO, он в конечном итоге все это понял. Аналогично для компиляции файла DOCO.
Когда вы отправляете-объявляете такой класс, вы не сможете создавать экземпляры этого класса до тех пор, пока класс не будет определен. Однако вы можете создавать указатели или ссылки на этот класс. Поэтому, если ваша структура DOCO должна иметь симулятор и наоборот, сделайте их содержащими элементы указателя, а не членами объекта.
Я уверен, что вы не хотели называть объявлять классы.
int main()
{
RandomNumberGen R;
Simulator S;
Pellet P;
DOCO D;
system("pause");
return 0;
}
RandomNumberGen
, вполне законно ссылаться на тип как на class RandomNumberGen
. Проблема в том, что (при условии, что это весь исходный файл) имена классов не видны. Удаление ключевых слов class
и struct
просто изменит сообщение об ошибке.