2013-12-18 69 views
1

我有好幾個文件,而且我的錯誤很奇怪。我不知道它是否會成爲問題的一部分,我使用XCode與OpenGL/SDL一起工作,並使用CMake創建了這些文件。即使使用ifndef也會導致C++重新定義錯誤

我有文件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" 

代碼工作很好,直到我把文件controls.hpp或/和controls.cpp中的#include「Wall.hpp」。 我正面臨錯誤「重新定義牆」,並且在此之後「gl.h包含在glew.h之前」。

+1

您的問題與定義有關。如果您希望我們幫助您,您至少需要包含違規定義(Wall)。我想你在頭文件中有一些定義。 –

+0

至於GL/GLEW錯誤,'Controls.cpp'首先包含'glfw.h',所以可能就是這樣。 – Angew

+11

兩件事:首先不包括源文件!將每個文件分別編譯爲目標文件,然後將它們鏈接在一起。其次,不要有帶前導下劃線的全局標識符名稱(比如include guard宏,例如'_WALL_H')。具有前導下劃線的名稱是保留的。 –

回答

1

我認爲這個問題是在你的方式包括在controls.cpp標題:

Wall.hpp - >類WALL定義

controls.hpp - >包括wall.hpp

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

所以基本上在controls.cpp中你包括了兩次類WALL的definitian;這可能是你錯誤的原因。如果你只包含controls.hpp,那麼你應該排除錯誤

+1

當然包括警衛(#ifndef _WALL_H)應該防止這種情況發生? – harmic

+0

它曾經工作過,但包含「Wall.hpp」的要點是在控件文件的函數中使用Wall作爲參數。 這就是爲什麼我試圖把包括後衛。 – Kevin

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++程序員堅持規定每個類應該在單獨的文件中定義。這不是絕對必要的,但可以更容易維護代碼。

+0

我尊重所有這些規則,只是我在文件main.cpp中創建了一個#include「Player.cpp」 。我不想要,但我沒有選擇,我在更改它時遇到以下錯誤: 架構x86_64的未定義符號: 「Player :: getLifePoints()」,引用來自: _main in runforyourcheese.o 「Player :: Player()」,引用來自: _main in runforyourcheese.o ld:找不到架構x86_64的符號 clang:錯誤:linker命令失敗,退出代碼爲1(使用-v看到調用) – Kevin

相關問題