Проблема c #include C++

92
03 мая 2021, 05:30

у меня есть два класса Player и MapEditor , в классе Player я использую MapEditor, а в MapEditor я использую Player. Я забыл как называется это проблема но когда я пишу в Player.h , #include "MapEditor.h", а в MapEditor.h я пишу #include "Player.h", то у меня весь error list забит ошибками типо syntaxis error 'MapEditor' , undeclared identifer, также это мелочь конечно но подсветка синтаксиса в классах перестаёт работать. Кто нибудь знает в чем проблема?

TileMap.h -

  #ifndef TILEMAP_H
#define TILEMAP_H

#include "Tile.h"

class MapEditor
{
private:
    void clear();
    float gridSizeF;
    unsigned gridSizeU;
    sf::Vector2f maxSizeWorldGrid;
    sf::Vector2f maxSizeF;
    sf::RenderWindow * window;
    unsigned layers;
    std::vector < std::vector < std::vector < Tile*> > > map;
    sf::RectangleShape TileSet;
    sf::RectangleShape collisionBox;
    sf::Texture textureSheet;
    std::string textureFile;
    sf::Vector2i pixelPos;
    sf::Vector2f pos;
    void initTextures();
    void initTileSet();
public:
    MapEditor(sf::RenderWindow * window,std::string textureFile);
    virtual ~MapEditor();
    void addTile(const unsigned  x, const unsigned y, const unsigned z, sf::IntRect& textureRect,const bool collision,const short type);
    void removeTile(const unsigned  x, const unsigned y, const unsigned z);
    sf::Texture &getTextureSheet();
    void saveToFile(const std::string filename);
    void loadFromFile(const std::string filename);
    void checkCollision(Player * player);
    const sf::Vector2f & getMapSize() const;
    const unsigned & getLayerCount() const;
    const std::vector<std::vector<std::vector<Tile*> > >& getTiles() const;
    void update(float time);
    void render(sf::RenderWindow& window);

};

#endif // ! TILEMAP_H

Player.h -

#ifndef PLAYER_H
#define PLAYER_H
#include "Entity.h"

class Player {
protected:
    AnimationManager anim;
    float posX, posY, dx, dy;
    float speed;
    enum MovementDirection {
        STAY,
        LEFT,
        RIGHT,
        JUMP,
        TOP,
        DOWN
    };
    sf::Sprite sprite;
    MovementDirection state;
    bool playerOnGround;

    bool life;
    unsigned hp;

public:
    Player(float x, float y, sf::Texture & texture,  std::string anim_file);
    virtual ~Player();
    const bool& checkLife() const;
    void movement(float time);
    void checkCollision(float Dx,float Dy);
    const sf::FloatRect& getRect() const;
    virtual const sf::Vector2f& getPosition() const;
    void update(float time);
    void render(sf::RenderWindow * window);
};

#endif //CATCHONBUBBLE_PLAYER_H
Answer 1

Суть проблемы: при использовании директивы #include компилятор вставляет код из включаемого файла туда, где эта директива прописана. Если у Вас используется такое взаимное включение, как описано в вопросе, возникает неявная рекурсия: один файл включает другой, который вновь включает первый, а тот, в свою очередь, снова включает второй и т.д. Это приводит к множественному переопределению всего, что объявлено в этих файлах.

Такая проблема обычно решается выполнением следующих шагов:

  1. Необходимо всё объявления классов оставить в .h-файлах, а реализацию всех методов вынести в одноимённые .c/.cpp-файлы
  2. Далее, при необходимости взаимного включения, нужно делать его не в .h, а в .c/.cpp-файлах. Например, в файл X.cpp написать #include"Y.h", а в Y.cpp написать #include"X.h"
  3. Если в объявлениях классов (в .h-файлах) встречаются имена классов из включаемых файлов, необходимо прописать там class Название_класса;, что даст понять компилятору, что этот класс объявлен где-то ещё

Также следовало бы добавить, #pragma once в начале .h-файлов. Это не спасает от представленной проблемы, но спасёт от множества потенциальных.

Меня такая инструкция не раз спасала от проблем, подобных описанной в вопросе.

В представленном коде пункт №1, по всей видимости, уже выполнен.

READ ALSO
Не выходит проверка на введенные пользователем значения

Не выходит проверка на введенные пользователем значения

Код ошибок не вызывает, однако, при запуске кода - он даже не ждет пока пользователь введет значение и просто закрываетсяКак это исправить?...

97
Может ли функция не иметь имени?

Может ли функция не иметь имени?

Может ли функция не иметь имени?

81
Non-static class function - pointer

Non-static class function - pointer

В ранних версиях Android NDK использовался gnustl

109
Размытие шрифта при установки значения bold

Размытие шрифта при установки значения bold

Слева требуемы результат, справа как получается у меня:

114