Как вы предотвращаете непрерывный цикл операторов #include? - PullRequest
1 голос
/ 22 июня 2011

У меня проблема с двумя классами, которые каждый должен знать о другом в своем заголовочном файле.

Structure.h

#ifndef STRUCTURE_H
#define STRUCTURE_H

#include <vector>
#include "Sprite.h"
#include "Bullet.h"

class Structure: public Sprite{
public:
Structure(const BITMAP bm, const Vec2& pos, const Vec2& vel,
              const RECT boundaries, std::vector<std::vector<bool>> holes);
virtual ~Structure() = 0;

void takeDamage(const Bullet* bullet);
protected:
std::vector<std::vector<bool>> mBulletHoles;
};

#endif

Structure.cpp

#include "Structure.h"

Structure::Structure(const BITMAP bm, const Vec2& pos, const Vec2& vel,
                     const RECT boundaries, std::vector<std::vector<bool>> holes)
    :Sprite(bm, pos, vel, boundaries),
     mBulletHoles(holes)
{}

void Structure::takeDamage(const Bullet* bullet){

}

Sprite::~Sprite(){}

Bullet.h

#ifndef BULLET_H
#define BULLET_H

#include "Animate.h"
#include "Structure.h"

class Bullet: public Sprite{
public:
Bullet(const BITMAP bm, const Vec2& pos, const Vec2& vel, const RECT boundaries, 
           bool friendly);
virtual ~Bullet();

int checkCollision(Animate* target);
void checkCollision(Structure* target, float dt);

private:
float mTimeSinceCollision;

bool mFriendly;
bool mActive;

const static float mPenetrationTime;
};

#endif

Bullet.cpp

#include "Bullet.h"

Bullet::Bullet(const BITMAP bm, const Vec2& pos, const Vec2& vel,
               const RECT boundaries, bool friendly)
:Sprite(bm, pos, vel, boundaries),
 mTimeSinceCollision(0.0f),
 mFriendly(friendly),
 mActive(true)
{}

int Bullet::checkCollision(Animate* target){
int returnPoints = 0;
if((target->identifier() == "Player") && !mFriendly){
    if(isTouching(target)){
        target->takeDamage();
        mActive = false;
    }
}else if((target->identifier() == "Alien") && mFriendly){
    if(isTouching(target)){
        returnPoints = target->takeDamage();
        mActive = false;
    }
}
return returnPoints;
}

void Bullet::checkCollision(Structure* target, float dt){
if(isTouching(target)){
    mTimeSinceCollision += dt;
    target->takeDamage(this);
}
if(mTimeSinceCollision >= mPenetrationTime){
    mActive = false;
}
}

Bullet::~Bullet(){}

const float Bullet::mPenetrationTime = .05;

, поскольку два заголовочных файла вызывают друг друга, я получаю много ошибок.Я устал заменять

#include "Bullet.h"

в Structure.h на

class Bullet;

, но потом компилятор сказал, что у меня есть несколько определенных типов.Как вы можете обойти зацикливание операторов #include?

Ответы [ 5 ]

5 голосов
/ 22 июня 2011

Во-первых, вы хотите избежать тех круговых включений.Затем, если на самом деле нет выхода, вы просто объявляете нужный класс в заголовке.

Например, в Bullet.h:

#include "Sprite.h"

class Structure; // Can now use Structure* and Structure&
class Bullet {
...
}

В Bullet.cpp

#include "Bullet.h"
#include "Structure.h"

В Structure.h:

#include "Sprite.h"

class Bullet;   // Can now use Bullet* and Bullet&
class Structure {
...
}

В Structure.cpp

#include "Structure.h"
#include "Bullet.h"

Когда компилятор увидит неизвестный объект "Sprite" в Bulletреализации, он будет знать, что вы ссылаетесь на конкретный объект, так как вы объявили в заголовке.См., Например, C ++ Lite Lite .

1 голос
/ 22 июня 2011

проблема в том, что вы включаете заголовки друг в друга.Т.е. вы включаете структуру в маркер и наоборот, что вызывает многократную ошибку включения.Предохранители включения, которые у вас есть, предотвращают это, но я все еще нахожу, что это происходит в некоторых случаях, и это один из них.

0 голосов
/ 22 июня 2011

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

# прагма один раз проверяет текущий файлвключен только один раз в одну компиляцию, для получения дополнительной информации о #pragma при посещении http://en.wikipedia.org/wiki/Pragma_once

0 голосов
/ 22 июня 2011

Используйте указатель на класс вместо класса в одном из файлов и выделите его через newdelete это в dtor, ofc).

Дело в том, что размер указателя ВСЕГДА известен компилятору, поэтому он не будет жаловаться и компилировать ваш код.Это называется предварительное объявление .Это очень хорошо задокументировано.

0 голосов
/ 22 июня 2011

В файле заголовка, если у вас нет ничего, кроме указателей на этот класс (члены и / или параметры / типы возврата), вы можете использовать прямое объявление вместо включения заголовка:

class Bullet;

Вам все еще нужно включить и Structure.h, и Bullet.h в файл cpp, потому что для него требуется полное определение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...