4

我最近一直在为多个文件包含错误而苦苦挣扎。我正在开发一款太空街机游戏,并将我的类/对象划分为不同的 .cpp 文件,并确保一切仍能正常工作,我构建了以下头文件:

#ifndef SPACEGAME_H_INCLUDED
#define SPACEGAME_H_INCLUDED
//Some Main constants
#define PI 3.14159265


//Standard includes
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;

//SDL headers
#include "SDL.h"
#include "SDL_opengl.h"
#include "SDL_mixer.h"
#include "SDL_image.h"

//Classes and project files
#include "Player.cpp"
#include "planet.cpp"
#include "Destructable.cpp"
#include "PowerUp.cpp"
#include "PowerUp_Speed.cpp"

#endif // SPACEGAME_H_INCLUDED

在我的每个文件的顶部,我(仅)包含了这个包含所有 .cpp 文件和标准包含的头文件。

但是,我有一个 Player/Ship 类,它给了我“重新定义 Ship 类”类型的错误。我最终通过在类定义文件中包含预处理器 #ifndef 和 #define 命令找到了一种解决方法:

#ifndef PLAYER_H
#define PLAYER_H
/** Player class that controls the flying object used for the space game */
#include "SpaceGame.h"


struct Bullet
{
  float x, y;
  float velX, velY;
  bool isAlive;
};

class Ship
{
    Ship(float sX,float sY, int w, int h, float velocity, int cw, int ch)
    {
        up = false; down = false; left = false; right = false;
        angle = 0;
....
#endif

通过这种解决方法,我丢失了“类/结构重定义”错误,但它在我的类文件 PowerUp_Speed 中给了我需要 Ship 类的奇怪错误:

#include "SpaceGame.h"

class PowerUp_Speed : public PowerUp
{

    public:
        PowerUp_Speed()
        {
            texture = loadTexture("sprites/Planet1.png");
        }

        void boostPlayer(Ship &ship)
        {
            ship.vel += 0.2f;
        }
};

我收到以下错误:“不完整类型 'struct Ship' 的使用无效”和“ 'struct ship' 的前向声明

我相信这些错误的根源仍然是多个文件包含错误的问题。我描述了我为减少错误数量而采取的每一步,但到目前为止,我在 Google 上找到的所有帖子都没有帮助我,所以我礼貌地问你们是否有人可以帮助我找到问题和修复。

4

1 回答 1

9

通常,您不包含 cpp 文件。
您只需要包含头文件!

当您包含 cpp 文件时,您最终会破坏One Definition Rule(ODR)
通常,您的头文件(.h)将定义类/结构等,而您的源(.cpp)文件将定义成员函数等。
根据ODR,您只能定义每个变量/函数等,包括相同的 cpp多个文件中的文件会创建多个定义,因此会破坏 ODR。

你应该怎么做?

请注意,为了能够创建对象或调用成员函数等,您需要做的就是在需要创建对象等的源文件中包含定义该类的头文件。您不需要在任何地方包含源文件.

前向声明呢?

总是首选使用前向声明类或结构而不是包含头文件,这样做具有显着的优势,例如:

  • 减少编译时间
  • 不污染全局命名空间。
  • 预处理器名称没有潜在的冲突。
  • 二进制大小没有增加(在某些情况下,但并非总是如此)

但是,一旦您转发声明一个类型,您只能对其执行有限的操作,因为编译器将其视为Incomplete Type。所以你应该总是尝试转发声明,但你不能总是这样做

于 2012-06-17T11:51:40.017 回答