Joe*_*ewd 4 c++ file redefinition inclusion
我最近一直在努力解决多个文件包含错误.我正在开发一个太空街机游戏并将我的类/对象划分为不同的.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
Run Code Online (Sandbox Code Playgroud)
在我的每个文件的顶部,我包括(仅)此头文件,其中包含所有.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
Run Code Online (Sandbox Code Playgroud)
通过这种解决方法,我丢失了'class/struct redefinition'erorrs但它在我的类文件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;
}
};
Run Code Online (Sandbox Code Playgroud)
我一直遇到以下错误:' 无效使用不完整类型'struct Ship' '和'struct declaration of'struct ship' '
我相信这些错误的起源仍然存在于多文件包含错误的麻烦中.我描述了我为减少错误数量而采取的每一步措施,但到目前为止,我在谷歌上发现的所有帖子都没有帮助我,这就是为什么我礼貌地问你是否有人能帮助我找到原因.问题和解决方法.
通常,您不包含cpp文件.
您只需要包含头文件!
当您包含cpp文件时,最终会破坏一个定义规则(ODR).
通常,您的头文件(.h)将定义类/结构等,您的源(.cpp)文件将定义成员函数等
.根据ODR,您只能定义每个变量/函数等,包括相同的cpp多个文件中的文件会创建多个定义,从而打破ODR.
你应该怎么做?
请注意,为了能够创建对象或调用成员函数等,您需要做的就是包含头文件,该文件在源文件中定义需要创建对象的类等.您不需要在任何地方包含源文件.
前言宣言怎么样?
始终首选使用前向声明类或结构而不是包含头文件,这样做具有明显的优势,例如:
但是,一旦转发声明类型,您只能对其执行有限的操作,因为编译器将其视为不完整类型.因此,您应该始终尝试转发声明,但始终不能这样做.