即使使用 ifndef,C++ 重定义错误
c++ redefinition error even with ifndef
我有几个文件,我的错误很奇怪。我不知道这是否可能是问题的一部分,我使用OpenGL/SDL,XCode,并使用CMake创建文件。
我有文件Wall.hpp,Wall.cpp,Player.hpp,Player.cpp,controls.hpp,controls.cpp,main.cpp。
以下是文件包含的摘要:
播放器.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;
};
播放器.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
墙.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
控件.hpp
#ifndef _MACRO_CONTROLS_C
#define _MACRO_CONTROLS_C
#include <vector>
#include "Wall.hpp"
...
#endif
控件.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
主.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"放入文件控件.hpp或/和控件中.cpp。我正面临错误"重新定义墙",以及在此之后"Gl.h 包含在 glew.h 之前"。
我认为问题在于您在controls.cpp
中包含标题的方式:
Wall.hpp
->类墙的定义
controls.hpp
-> 包括 wall.hpp
controls.cpp
-> includes wall.hpp and controls.hpp
所以基本上在控件中.cpp你包含了两次类 WALL 的定义者;这可能是你错误的原因。如果您只包含 controls.hpp,您应该摆脱错误
这里没有足够的信息来准确回答为什么您会看到问题中列出的错误。这可能是由某种递归包含循环引起的,尽管我还没有发现它。
但是,我认为如果您遵循一些基本的C++卫生习惯,这些问题就会消失。
不要包含 cpp 文件。您应该分别编译其中的每一个,然后使用链接器将它们链接在一起。我不熟悉 XCode,但如果项目设置正确,大多数 IDE 将能够自动执行此操作。使用外部生成文件来处理这些任务也很常见。
在评论中,您提到当您不包含来自main.cpp的cpp文件时,您遇到了符号解析错误。这很可能意味着我上面提到的链接步骤没有正确完成。
在每个头文件 (hpp) 中放置包含保护,但不在 cpp 文件中放置(它们不是必需的,因为从步骤 1 开始,您不包括它们)。
我过去发现很多问题源于不正确的包括警卫。
最常见的是从一个文件复制/粘贴到另一个文件,而忘记更改宏名称。
另一个可能发生的情况是,包含树中有多个目录,同名文件位于两个不同的目录中。在这种情况下,您需要在保护宏名称中包含目录名称。
然而,问题的另一个来源可能是 #if/#endif 对不匹配。在大多数情况下,这是显而易见的,因为预处理器会抱怨,但是如果您有两组不匹配对,那么它可能会产生意外的结果。最好在 #endif 后放置注释以显示它们与哪个警卫相关联,例如:
#ifndef WALL_H #define WALL_H ... #endif /* WALL_H */
一些 IDE(例如Eclipse CDT) 将自动以这种格式添加这些守卫。
不要在保护宏(或任何其他宏)中包含前导下划线,以避免与系统定义的宏发生可能的冲突。
在每个文件(cpp 或 hpp)中,仅包含定义您在该文件中使用的类、函数、变量等所需的 hpp 文件。
每个 cpp 文件都应该有一个相应的 hpp 文件,该文件声明了相应 cpp 文件中定义的项目。cpp 文件应包含 hpp 文件。hpp 文件包含的任何内容都不需要由 cpp 文件重新包含。
许多C++程序员坚持每个类都应该在单独的文件中定义的规则。这不是绝对必要的,但可以更轻松地维护代码。
- 使用命名空间时出现多个定义错误
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- 尝试调用 .h 文件中定义的变量时出现变量未定义错误
- 在头文件和 cpp 文件中使用一次 #pragma 时出现结构重定义错误
- 链接阶段出现多重定义错误
- 避免模板类中的重定义错误
- 即使我没有包含多个文件,C++中的多个定义错误
- 跨多个类的全局变量而不会出现重定义错误?
- 尝试运行 wasm 函数时出现模块未定义错误
- C++ 预期的左大括号以及重定义错误
- C++:成员的越界声明必须是纯虚函数的定义错误
- c++中数组的未定义错误
- Visual C:模板类中的自定义错误消息
- 为什么C++模板不会导致多个定义错误?
- 只有一个定义/声明时标头声明变量的多堆定义错误
- C++ 在多个其他类中使用单个类 - 编译时出现多个定义错误
- 基类未定义.错误 C2504
- Q 斯坦达项重定义错误
- 可视化C++中的结构定义错误
- VC++ C2011 重定义错误 - 未使用的头文件