你如何防止不断循环#include语句?

时间:2011-06-22 14:00:25

标签: c++ visual-c++

我遇到了两个类的问题,每个类都需要在头文件中了解另一个类。

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 个答案:

答案 0 :(得分:5)

首先,你要避免那些循环包含。然后,如果真的没有出路,你只需在标题中声明所需的类。

例如,在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"

当编译器在Bullet实现中看到未知的“Sprite”对象时,他会知道你指的是一个特定的对象,因为你在头文件中声明了。例如,请参阅C++ FAQ Lite

答案 1 :(得分:1)

问题是你是否将标题包含在彼此中。即你在子弹中包含结构,反之亦然,这会导致多重包含错误。你拥有的包含守卫防止了这种情况,但我仍然发现在某些情况下会发生这种情况,这就是其中之一。

答案 2 :(得分:0)

在头文件中,如果除了指向该类的指针(成员和/或参数/返回类型)之外没有任何其他内容,则可以使用前向声明而不是包含标题:

class Bullet;

你仍然需要在cpp文件中包含Structure.h和Bullet.h,因为它需要两者的完整定义。

答案 3 :(得分:0)

使用指向该类的指针而不是其中一个文件中的类,并通过new(和delete在dtor,ofc中)分配它。

问题是,指针的大小总是为编译器所知,所以它不会抱怨和编译你的代码。这称为前向声明。这是非常好的记录。

答案 4 :(得分:-1)

添加 #pragma一次会有所帮助,但是有一个更好的包含结构来避免循环也会很好。

#pragma once 确保当前文件仅在一次编辑中包含一次,有关#pragma一次访问的详细信息 http://en.wikipedia.org/wiki/Pragma_once