即使使用ifndef,c ++重新定义错误

时间:2013-12-18 09:04:57

标签: c++ opengl runtime-error sdl redefinition

我有几个文件,我的错误很奇怪。我不知道它是否可能是问题的一部分,我使用OpenGL / SDL,使用XCode,我使用CMake创建了文件。

我有文件Wall.hpp,Wall.cpp,Player.hpp,Player.cpp,controls.hpp,controls.cpp,main.cpp。

以下是文件包含的摘要:

// Player.hpp

#include <iostream>


class Player{
    public :
    Player();
    int getLifePoints();
    int getStaminaPoints();
    float getPosX();
    float getPosY();
    float getPosZ();

    void setPosX(float x);
    void setPosY(float y);
    void setPosZ(float z);

    void reducePoints(int damage);
    bool isHeroRunning();
    void changeHeroRun();
    bool isHeroDucking();
    void changeHeroDuck();


    private :
    int lifePoints;
    int staminaPoints;
    float posX;
    float posY;
    float posZ;
    bool isRunning;
    bool isDucking;

};

// Player.cpp

#include "Player.hpp"
using namespace std;

Player::Player(){
    this->lifePoints = 100;
    this->posX = 0;
    this->posY = 0;
    this->posZ = 0;
}

int Player::getLifePoints(){
    return this->lifePoints;
}
int Player::getStaminaPoints(){
    return this->staminaPoints;
}

float Player::getPosX(){
    return this->posX;
};
float Player::getPosY(){
    return this->posY;
};
float Player::getPosZ(){
    return this->posZ;
};

void Player::setPosX(float x){
    this->posX=x;
};
void Player::setPosZ(float z){
    this->posZ=z;
};
void Player::setPosY(float y){
    this->posY=y;
};

void Player::reducePoints(int damage){
    this->lifePoints= lifePoints - damage;
}

int lifePoints;
float posX;
float posY;
float posZ;

bool Player::isHeroRunning(){
    return isRunning;
}

void Player::changeHeroRun(){
    this->isRunning=!this->isRunning;
}

bool Player::isHeroDucking(){
    return this->isDucking;
}
void Player::changeHeroDuck(){
    this->isDucking=!this->isDucking;
    if (isDucking){
        this->posZ=this->posZ/2;
    } else {
        this->posZ=this->posZ*2;
    }
}

// Wall.hpp

#ifndef _WALL_H
#define _WALL_H

#include <iostream>
#include <vector>
// Include GLEW
#include <GL/glew.h>

// Include GLFW
#include <GL/glfw.h>

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

class Wall{
    public :
    Wall(GLfloat x1, GLfloat x2, GLfloat z1, GLfloat z2);
    //~Wall();
    GLfloat getX1();
    GLfloat getX2();
    GLfloat getY1();
    GLfloat getY2();
    GLfloat getZ1();
    GLfloat getZ2();
    int isInZone(GLfloat x, GLfloat y, GLfloat z);
    std::vector<GLfloat> add_wall (std::vector<GLfloat> walls);


private:
    GLfloat x1, x2, y1, y2, z1, z2;

};

#endif

// Wall.cpp

#ifndef _WALL_C
#define _WALL_C

// Include GLEW
#include <GL/glew.h>

// Include GLFW
#include <GL/glfw.h>

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "Wall.hpp"
#include <vector>

Wall::Wall(GLfloat x1, GLfloat x2, GLfloat z1, GLfloat z2){
    this->x1=x1;
    this->x2=x2;
    this->y1=y_floor;
    this->y2=y_ceiling;
    this->z1=z1;
    this->z2=z2;
}

#endif

// controls.hpp

#ifndef _MACRO_CONTROLS_C
#define _MACRO_CONTROLS_C

#include <vector>

#include "Wall.hpp"
...
#endif

// controls.cpp

#ifndef _MACRO_CONTROLS_C
#define _MACRO_CONTROLS_C


// Include GLFW
#include <GL/glfw.h>

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;

#include <iostream>

#include "controls.hpp"

#include <unistd.h>

#define GetCurrentDir getcwd

#include "Wall.hpp"
...
#endif

// main.cpp中

// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <list>
#include <vector>
#include <time.h>
#include <typeinfo>

// Include GLEW
#include <GL/glew.h>

// Include GLFW
#include <GL/glfw.h>

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;

#include <unistd.h>
#define GetCurrentDir getcwd

#include <common/shader.hpp>
#include <common/texture.hpp>
#include <common/controls.hpp>
#include "Player.cpp"
#include "Turret.hpp"

#include "Wall.hpp"

代码运行良好,直到我把#include“Wall.hpp”放在文件controls.hpp或/和controls.cpp中。 我正面临着“重新定义Wall”的错误,并且在“glew.h之前包含了gl.h”之后也是如此。

2 个答案:

答案 0 :(得分:1)

我认为问题在于您在controls.cpp中包含标题的方式:

Wall.hpp - &gt;类WALL的定义

controls.hpp - &gt;包括wall.hpp

controls.cpp - &gt; includes wall.hpp and controls.hpp

所以基本上在controls.cpp中你包括两次类WALL的定义;这可能是导致错误的原因。如果你只包含controls.hpp,你应该摆脱错误

答案 1 :(得分:0)

我认为这里没有足够的信息来准确回答您为什么会看到问题中列出的错误。它可能是由某种类型的递归包含循环引起的,尽管我还没有发现它。

但是,如果您遵循一些基本的C ++卫生习惯,我认为这些问题将会消失。

  1. 不要包含cpp文件。您应该分别编译这些中的每一个,然后使用链接器将它们链接在一起。我不熟悉XCode,但如果项目设置正确,大多数IDE都可以自动执行此操作。使用外部Makefile来处理这些任务也很常见。

    在您提到的评论中,当您没有包含main.cpp中的cpp文件时,您会收到符号解析错误。这很可能意味着上面提到的链接步骤没有正确完成。

  2. 将包含警戒放在每个标头(hpp)文件中但不包含在cpp文件中(因为从第1步开始不需要它们,所以不包含它们)。

  3. 我发现过去由于不正确的包含警卫而导致的许多问题。

    最常见的是从一个文件复制/粘贴到另一个文件而忘记更改宏名称。

    可能发生的另一个问题是,在包含树中有多个目录,在两个不同的目录中具有相同名称的文件。在这种情况下,您需要在保护宏名称中包含目录名称。

    另一个问题来源可能是#if / #endif对不匹配。在大多数情况下,这将是显而易见的,因为预处理器会抱怨,但如果你有两组不匹配的对,那么它可能会出乎意料的结果。最好在#endif之后放置注释以显示与之关联的警卫,例如:

    #ifndef WALL_H
    #define WALL_H
    
    ...
    
    #endif /* WALL_H */
    

    某些IDE(例如Eclipse CDT)会自动以这种格式添加这些警卫。

  4. 不要在保护宏(或任何其他宏)中包含前导下划线,以避免与系统定义的宏发生冲突。

  5. 在每个文件(cpp或hpp)中仅包含定义您在该文件中使用的类,函数,变量等所需的hpp文件。

  6. 每个cpp文件都应该有一个相应的hpp文件,该文件声明了相应cpp文件中定义的项目。 cpp文件应包含hpp文件。 hpp文件中包含的任何内容都不需要由cpp文件重新包含。

    许多C ++程序员坚持要求每个类都应在单独的文件中定义的规则。它不是绝对必要的,但可以更容易维护代码。