C++ C++#包括警卫

C++ C++#包括警卫,c++,header,include,include-guards,C++,Header,Include,Include Guards,解决 真正帮助我的是,我可以在.cpp文件中包含标题,而不会导致重新定义的错误 我是C++新手,但我在C++和java中有一些编程经验,所以我可能会错过一些C++特有的基本的东西。 问题是我真的不知道出了什么问题,我会粘贴一些代码来解释这个问题 我有三门课,GameEvents,Physics和GameObject。我为每一个都有标题。 GameEvents有一个物理和一个游戏对象列表。 物理有一个游戏对象列表 我试图实现的是,我希望GameObject能够访问或拥有一个物理对象 如果我只是把

解决

真正帮助我的是,我可以在.cpp文件中包含标题,而不会导致重新定义的错误


<>我是C++新手,但我在C++和java中有一些编程经验,所以我可能会错过一些C++特有的基本的东西。 问题是我真的不知道出了什么问题,我会粘贴一些代码来解释这个问题

我有三门课,GameEvents,Physics和GameObject。我为每一个都有标题。 GameEvents有一个物理和一个游戏对象列表。 物理有一个游戏对象列表

我试图实现的是,我希望GameObject能够访问或拥有一个物理对象

如果我只是把“Physics.h”包含在GameObject中,我会得到 “错误C2111:'ClassXXX':'class'类型重新定义”,我理解。 这就是我认为“包括后卫”会有所帮助的地方,所以我在物理中添加了一个“包括后卫”。h因为这是我想包括两次的标题

这就是它的样子

#ifndef PHYSICS_H
#define PHYSICS_H

#include "GameObject.h"
#include <list>


class Physics
{
private:
    double gravity;
    list<GameObject*> objects;
    list<GameObject*>::iterator i;
public:
    Physics(void);
    void ApplyPhysics(GameObject*);
    void UpdatePhysics(int);
    bool RectangleIntersect(SDL_Rect, SDL_Rect);
    Vector2X CheckCollisions(Vector2X, GameObject*);
};

#endif // PHYSICS_H
\ifndef物理学
#定义物理学
#包括“GameObject.h”
#包括
课堂物理
{
私人:
双重重力;
列出对象;
列表::迭代器i;
公众:
物理学(void);
无效应用物理(游戏对象*);
虚更新物理(int);
布尔矩形相交(SDL_Rect,SDL_Rect);
Vector2X检查碰撞(Vector2X,GameObject*);
};
#endif//物理学
但是如果我把“Physics.h”包含在我的GameObject.h中,现在就像这样:

#include "Texture2D.h"
#include "Vector2X.h"
#include <SDL.h>
#include "Physics.h"

class GameObject
{
private:
    SDL_Rect collisionBox;
public:
    Texture2D texture;
    Vector2X position;
    double gravityForce;
    int weight;
    bool isOnGround;
    GameObject(void);
    GameObject(Texture2D, Vector2X, int);
    void UpdateObject(int);
    void Draw(SDL_Surface*);
    void SetPosition(Vector2X);
    SDL_Rect GetCollisionBox();
};
class GameObject {
...
};

#include physics.h

class Physics {
...
};
a.h:
#ifndef A_H
#define A_H
class A { int a; };
#endif

b.h:
#ifndef B_H
#define B_H
#include "a.h"
class B { int b; };
#endif
#包括“Texture2D.h”
#包括“Vector2X.h”
#包括
#包括“Physics.h”
类游戏对象
{
私人:
SDL直接碰撞盒;
公众:
纹理2D纹理;
矢量2X位置;
双重重力;
整数权重;
布尔伊森格朗;
游戏对象(无效);
游戏对象(纹理2D,矢量2X,整数);
无效更新对象(int);
空洞绘制(SDL_表面*);
无效设置位置(矢量2X);
SDL_Rect GetCollisionBox();
};
我有很多问题不明白他们为什么会出现。 如果我不包括“Physics.h”,我的代码运行得很好


我非常感谢您的帮助。

问题是您的
GameObject.h
没有防护装置,因此当您
时,请包含“GameObject.h”
Physics.h
中,当
GameObject.h
包含
Physics.h

时,它会被包含在所有
*.h
*.hh
头文件中(除非您有特殊原因不这样做)


要了解发生了什么,请尝试获取源代码的预处理形式。对于GCC,它类似于
g++-Wall-C-E yourcode.cc>yourcode.i
(我不知道Microsoft编译器是如何做到这一点的)。您还可以询问包含哪些文件,GCC为
g++-Wall-H-cyourcode.cc
您在这里有循环引用:
Physics.H
包含
GameObject.H
,其中包括
Physics.H
。你的类
Physics
使用
GameObject*
(指针)类型,因此你不需要在
Physics.h
中包含
GameObject.h
,只需使用前向声明-而不是

#include "GameObject.h" 


此外,在每个头文件中放置防护装置。

首先,您还需要在gameobject上包含防护装置,但这不是真正的问题

如果其他东西包括物理。首先,物理。h包括游戏对象。h,你会得到这样的东西:

#include "Texture2D.h"
#include "Vector2X.h"
#include <SDL.h>
#include "Physics.h"

class GameObject
{
private:
    SDL_Rect collisionBox;
public:
    Texture2D texture;
    Vector2X position;
    double gravityForce;
    int weight;
    bool isOnGround;
    GameObject(void);
    GameObject(Texture2D, Vector2X, int);
    void UpdateObject(int);
    void Draw(SDL_Surface*);
    void SetPosition(Vector2X);
    SDL_Rect GetCollisionBox();
};
class GameObject {
...
};

#include physics.h

class Physics {
...
};
a.h:
#ifndef A_H
#define A_H
class A { int a; };
#endif

b.h:
#ifndef B_H
#define B_H
#include "a.h"
class B { int b; };
#endif
而#include physics.h由于include卫士而被丢弃,你最终会在物理声明之前声明GameObject

但若你们想让游戏对象有一个指向物理的指针,那个么这就是一个问题,因为对于htat来说,必须先声明物理

要解决该循环,您可以改为向前声明一个类,但前提是您仅将其用作以下声明中的指针或引用,即:

#ifndef PHYSICS_H
#define PHYSICS_H

//  no need for this now #include "GameObject.h"

#include <list>

class GameObject;

class Physics
{
private:
    list<GameObject*> objects;
    list<GameObject*>::iterator i;
public:
    void ApplyPhysics(GameObject*);
    Vector2X CheckCollisions(Vector2X, GameObject*);
};

#endif // PHYSICS_H
\ifndef物理学
#定义物理学
//现在不需要了#包括“GameObject.h”
#包括
类游戏对象;
课堂物理
{
私人:
列出对象;
列表::迭代器i;
公众:
无效应用物理(游戏对象*);
Vector2X检查碰撞(Vector2X,GameObject*);
};
#endif//物理学

在所有头文件中使用include guard。由于您使用的是Visual Studio,因此可以使用
#pragma once
作为所有标题中的第一个预处理器定义

但是,我建议使用经典方法:

#ifndef CLASS_NAME_H_
#define CLASS_NAME_H_

// Header code here

#endif //CLASS_NAME_H_

其次,阅读并应用它。

预处理器是一个程序,它接受您的程序,进行一些更改(例如包括文件(#include)、宏扩展(#define),以及基本上以
#
开头的所有内容),并向编译器提供“干净”的结果

当预处理器看到
#include
时,其工作方式如下:

当你写作时:

#include "some_file"
某些_文件的内容
几乎可以直接将副本粘贴到包含它的文件中。现在,如果您有:

a.h:
class A { int a; };
#include "b.h"

class A
{
    B b;
};
class A
{
    B *b;
};
以及:

以及:

你会得到:

main.cpp:
class A { int a; };  // From #include "a.h"
class A { int a; };  // From #include "b.h"
class B { int b; };  // From #include "b.h"
现在您可以看到如何重新定义
A

当你写守卫时,他们会变成这样:

#include "Texture2D.h"
#include "Vector2X.h"
#include <SDL.h>
#include "Physics.h"

class GameObject
{
private:
    SDL_Rect collisionBox;
public:
    Texture2D texture;
    Vector2X position;
    double gravityForce;
    int weight;
    bool isOnGround;
    GameObject(void);
    GameObject(Texture2D, Vector2X, int);
    void UpdateObject(int);
    void Draw(SDL_Surface*);
    void SetPosition(Vector2X);
    SDL_Rect GetCollisionBox();
};
class GameObject {
...
};

#include physics.h

class Physics {
...
};
a.h:
#ifndef A_H
#define A_H
class A { int a; };
#endif

b.h:
#ifndef B_H
#define B_H
#include "a.h"
class B { int b; };
#endif
现在,让我们看看如何扩展main中的
#includes(这与前面的情况完全相同:复制粘贴)

现在让我们跟随预处理器,看看从中产生了什么“真正的”代码。我会一行一行地说:

// From #include "a.h"
评论。忽视继续:

#ifndef A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#ifndef A_H          // From
class B { int b; };
#endif
是否定义了
A_H
?不然后继续:

#define A_H
#define B_H
好了,现在定义了
A_H
。继续:

#ifndef A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#ifndef A_H          // From
class B { int b; };
#endif
这不是预处理器的事情,所以就让它去吧。继续:

#ifndef A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#ifndef A_H          // From
class B { int b; };
#endif
前面的
if
在此处完成。继续:

#ifndef A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#ifndef A_H          // From
class B { int b; };
#endif
评论。忽视继续:

#ifndef A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#ifndef A_H          // From
class B { int b; };
#endif
是否定义了
B_H
?不然后继续:

#define A_H
#define B_H
现在确定
B_H
。继续:

#ifndef A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#ifndef A_H          // From
class B { int b; };
#endif
是否定义了
A_H
?对然后忽略,直到相应的
#endif

#define A_H          // #include "a.h"
忽略

class A { int a; };  // inside
#endif               // "b.h"
忽略

class A { int a; };  // inside
#endif               // "b.h"
前面的
if
在此处完成。继续:

#ifndef A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#ifndef A_H          // From
class B { int b; };
#endif
这不是我的事