【问题标题】:c++ redefinition error even with ifndef即使使用 ifndef,c ++ 重新定义错误
【发布时间】:2013-12-18 09:04:57
【问题描述】:

我有几个文件,我的错误很奇怪。我不知道这是否可能是问题的一部分,我使用 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”,并且在这个“Gl.h 包含在 glew.h 之前”之后。

【问题讨论】:

  • 您的问题与定义有关。如果您希望我们帮助您,您至少需要包含有问题的定义(Wall)。我猜你在头文件中有一些定义。
  • 至于GL/GLEW错误,Controls.cpp首先包括glfw.h,所以可能就是这样。
  • 两件事:首先不要包含源文件!将每个文件分别编译为目标文件,然后将它们链接在一起。其次,不要有带前导下划线的全局标识符名称(如包含保护宏,例如_WALL_H)。保留带有前导下划线的名称。
  • 请注意,以下划线后跟大写字母开头的名称在所有上下文中都保留用于实现(C++ 编译器及其标准库)。
  • 抱歉没有放上Wall的定义。

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


【解决方案1】:

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

Wall.hpp -> 类 WALL 的定义

controls.hpp -> 包括 wall.hpp

controls.cpp -> includes wall.hpp and controls.hpp

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

【讨论】:

  • 当然包含防护 (#ifndef _WALL_H) 应该防止这种情况发生?
  • 它曾经可以工作,但包含“Wall.hpp”的全部意义在于使用 Wall 的向量作为控制文件中函数的参数。这就是我尝试放置包含保护的原因。
【解决方案2】:

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

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

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

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

  2. 在每个头文件 (hpp) 中添加包含保护,但不在 cpp 文件中(不需要它们,因为从第 1 步开始,您不包含它们)。

  3. 过去我发现很多问题源于不正确的包含守卫。

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

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

    另一个问题来源可能是不匹配的 #if / #endif 对。在大多数情况下,这很明显,因为预处理器会抱怨,但如果你有两组不匹配的对,那么它甚至可能会产生意想不到的结果。最好将 cmets 放在 #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++ 程序员坚持每个类都应该在单独的文件中定义的规则。这不是绝对必要的,但可以更容易地维护代码。

【讨论】:

  • 我尊重所有这些规则,除了我在文件 main.cpp 中创建了一个#include "Player.cpp"。我不想,但我真的别无选择,当我更改它时遇到以下错误:架构 x86_64 的未定义符号:“Player::getLifePoints()”,引用自:runforyourcheese.o 中的 _main “Player::Player()”,引用自:runforyourcheese.o 中的 _main ld:未找到架构 x86_64 的符号:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用)
猜你喜欢
  • 2021-07-21
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多