簡體   English   中英

為什么包括警衛對我沒有效果? 我想念什么嗎?

[英]Why include guards gives no effect for me? Am I missing something?

MainGame.h

#ifndef MainGame_h
#define MainGame_h

#include <string>
#include <sstream>
#include "Horde3D.h"

//definitions

#endif MainGame_h

MainGame.cpp

#include <math.h>
#include <iomanip>
#include "Horde3DUtils.h"
#include "MainGame.h"
#include "GameConfig.h" //<--

//code

main.cpp中

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

#include "glfw.h"
#include "MainGame.h"
#include "GameConfig.h" //<--

//code

GameConfig.h

#ifndef GameConfig_h
#define GameConfig_h

#include <string>
#include <sstream>

#define MAX_PATH 260

class GameConfig
{
    static std::string ExtractStartupPath(char *full_app_path)
    {
        const std::string s(full_app_path);

        if(s.find( "/" ) != std::string::npos)
            return s.substr( 0, s.rfind( "/" )) + "/";
        else if(s.find( "\\" ) != std::string::npos )
            return s.substr( 0, s.rfind( "\\" )) + "\\";
        else
            return "";
    }

public:
    static bool IsFullScreen;
    static int StatMode;
    static int FreezeMode;
    static bool DebugViewMode;
    static bool WireframeMode;
    static char *GameTitle;
    static int WindowWidth, WindowHeight;
    static char StartupPath[MAX_PATH];
    static char ContentPath[MAX_PATH];

    static void Initialize(char *startup_path)
    {
        GameTitle = "TestGame\0";

        std::string startup_dir = ExtractStartupPath(startup_path);
        memcpy(StartupPath, startup_dir.c_str(), startup_dir.length() * sizeof(char));

        std::string path(StartupPath);
        path.erase(path.find_last_of('\\'), std::string::npos);
        path.append("\\Content");
        memcpy(ContentPath, path.c_str(), path.length() * sizeof(char));
    }
};

int GameConfig::StatMode = 0;
int GameConfig::FreezeMode = 0;
bool GameConfig::DebugViewMode = false;
bool GameConfig::WireframeMode = false;
bool GameConfig::IsFullScreen = false;
int GameConfig::WindowWidth = 800;
int GameConfig::WindowHeight = 600;
char GameConfig::StartupPath[MAX_PATH] = { 0 };
char GameConfig::ContentPath[MAX_PATH] = { 0 };
char *GameConfig::GameTitle = "TestGame\0";

#endif GameConfig_h

編譯時出現鏈接器錯誤...

main.obj : error LNK2005: "public: static int GameConfig::StatMode" (?StatMode@GameConfig@@2HA) is already define in в MainGame.obj

但是我不明白為什么……GameConfig僅包含兩個內容-一個在MainGame.cpp中 ,另一個在main.cpp中 那些永遠都不會越過。 即使他們越過,那么#ifndef GameConfig_h#define GameConfig_h#endif GameConfig會做什么呢?

我使用VC ++ 2010 Express Edition

包含保護有助於您避免同一翻譯單元多次包含同一文件。 但是,由於翻譯單元是獨立處理的,因此它們兩個都將獲得包含的代碼,因此會產生重復的定義。

為避免此問題,您需要將定義移出標頭並移入CPP文件:

GameConfig.cpp:

#include "GameConfig.h"

int GameConfig::StatMode = 0;
int GameConfig::FreezeMode = 0;
bool GameConfig::DebugViewMode = false;
bool GameConfig::WireframeMode = false;
bool GameConfig::IsFullScreen = false;
int GameConfig::WindowWidth = 800;
int GameConfig::WindowHeight = 600;
char GameConfig::StartupPath[MAX_PATH] = { 0 };
char GameConfig::ContentPath[MAX_PATH] = { 0 };
char *GameConfig::GameTitle = "TestGame\0";

包含保護僅在單個編譯單元 (即單個cpp文件) 內部有用。 由於cpp文件是分別編譯的,因此對於每個文件,include防護將以未定義形式啟動,因此.h文件將被包含兩次,每個cpp文件一次。 如果.h文件包含例如函數定義,它將被定義兩次。

通常,通過僅將聲明放在h文件中,並實際上在cpp文件中定義函數,可以使問題“消失”。 這樣,該功能將僅定義一次。

您需要將靜態的初始化移動到GameConfig.cpp。

當前,每個包含GameConfig.h的源文件都將獲取這些變量的自己的副本。

靜態成員的實例化不應在.h文件中,而應在相應的.cc文件中。

否則,它們將在每個編譯單元中實例化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM