Ошибка 2061 — класс становится «неопределенным» при включении заголовка

#c

#c

Вопрос:

Это очень странно, и я не могу понять, что является его причиной…. Итак, у меня есть два класса: Player и Enemy и служебный статический класс CollisionMgr.

У меня есть массив врагов мирового класса, я хотел бы иметь указатель на него в классе Player для обнаружения столкновений. Но в тот момент, когда я пытаюсь #включить вражеский класс в player one, я получаю ошибку «Игрок не определен» во вражеском…. Я думаю, что это связано с включениями заголовка…

     #pragma once
    #include <string>
    #include <vector>

    #include "mathlib.h"
    #include "md2model.h"
    #include "Object3DS.h"



    const float PLAYER_FORWARD_SPEED = 60.0f;
    const float PLAYER_HEADING_SPEED = 60.0f;

    class Player : public GameObject
    {
    public:

        Player(float r);
        ~Player();

        void loadModel(const char *filename);
        void drawModel();
        void drawBoundingWireframe();
        void passVisibleObjects(vector<Object3DS*> amp;vo);

    private:
    Entity3D entity;
MD2Model* player;

float modelRot;
float modelPitch;

Vector3 scale;
Vector3 pos;
Vector3 rot;

float forwardSpeed;
float heading;

float radius;


vector<Object3DS*> visibleObjects;

    };
  

И это вражеский класс

     #pragma once
    #include <string>
    #include <vector>

    #include "Player.h"
    #include "mathlib.h"
    #include "md2model.h"


    const float ENEMY_FORWARD_SPEED = 60.0f;
    const float ENEMY_HEADING_SPEED = 60.0f;

    class Enemy : public GameObject
    {
    public:

Enemy(Player* p, float r);
~Enemy();

void loadModel(const char *filename);
void drawModel();
void drawBoundingWireframe();


bool checkCollision();

void setPosition(Vector3 pos);
void setRotation(Vector3 r);
void setScale(Vector3 r);


void setSpeed(float s);
void setHeading(float h);
float getForwardSpeed();
float getHeading();
void rotateModel(float dx, float dy);
void resetRotation();

void setAnimation(char *filename);

Vector3 getPosition();
void moveEnemy(float elapsedTimeSec);

Entity3D entity;

void passVisibleObjects(vector<Object3DS*> amp;vo);



    private:
MD2Model* enemy;

Player* player;

float modelRot;
float modelPitch;

Vector3 scale;
Vector3 pos;
Vector3 rot;

float forwardSpeed;
float heading;

float radius;

vector<Object3DS*> visibleObjects;

    };
  

В исходных файлах я включаю этот статический класс с некоторыми функциями столкновения:

     #pragma once


    #include <vector>
    #include "mathlib.h"
    #include "Object3DS.h"

    #include "Enemy.h"

    class CollisionMgr{


    public:

static vector<Object3DS*> findVisibleObjects(BoundingBox amp;viewingVolume,                 vector<Object3DS> amp;gameObjects, vector<Object3DS*> amp;visibleObjects);
static vector<Enemy*> findVisibleEnemies(BoundingBox amp;viewingVolume, vector<Enemy> amp;enemies, vector<Enemy*> amp;visibleEnemies);
static bool checkCollision(const Vector3 pos, const Vector3 forward, float radius, const vector<Object3DS*> amp;vo);
static double intersectRaySphere(Vector3 rO, Vector3 rV, Vector3 sO, double sR);


    };
  

Все это компилируется нормально, но в тот момент, когда я пытаюсь добавить #include «Enemy» в Player, я получаю ошибку C2061: синтаксическая ошибка: идентификатор ‘Player’ внутри класса Enemy …. или, если я успешно включаю Enemy, а затем пытаюсь включить CollisionMgr …. естькакой-то конфликт между ними двумя и определением Player, но я не могу понять, как его разрешить….

Я использую VS2010 в качестве своего компилятора..

Любая помощь будет оценена!

Я попытался перестроить операторы включения, но я действительно не понимаю, что является причиной этого?

Ответ №1:

Это случай циклической зависимости. Вам нужно будет правильно переслать declare Player и Enemy , и вы не сможете использовать их определения в противоположном файле заголовка. Вы можете использовать их в файле реализации. Вот пример:

Player.h

 class Player
{
   // needs to know about Enemy
   void f(const Enemyamp; b);
};
  

Enemy.h

 class Enemy
{
   // needs to know about Player 
   void f(const Playeramp; a);
};
  

Включение файла заголовка в обоих расположениях приведет к ошибке (как вы видите):

Player.h

 // This isn't going to work...
#include "Enemy.h"
class Player
{
   // needs to know about Enemy
   void f(const Enemyamp; b);
};
  

Enemy.h

 // This isn't going to work...
#include "Player.h"

class Enemy
{
   // needs to know about Player 
   void f(const Playeramp; a);
};
  

Здесь необходимо «прямое объявление» для Player и Enemy , где это уместно, например:

Player.h

 // forward declaration:
class Enemy;

class Player
{
   // needs to know about Enemy
   void f(const Enemyamp; b);
};
  

Enemy.h

 // forward declaration
class Player;

class Enemy
{
   // needs to know about Player 
   void f(const Playeramp; a);
};
  

Затем в файлах реализации вы можете #include использовать соответствующие заголовки, чтобы фактически получить определения объектов в вашем модуле компиляции.