简体   繁体   English

为什么包括警卫对我没有效果? 我想念什么吗?

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

MainGame.h MainGame.h

#ifndef MainGame_h
#define MainGame_h

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

//definitions

#endif MainGame_h

MainGame.cpp MainGame.cpp

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

//code

main.cpp main.cpp中

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

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

//code

GameConfig.h 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

When compiling it I getting linker errors... 编译时出现链接器错误...

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

But I don't understand why... There are only two includes of GameConfig - one in MainGame.cpp and second in main.cpp . 但是我不明白为什么……GameConfig仅包含两个内容-一个在MainGame.cpp中 ,另一个在main.cpp中 Those should never cross. 那些永远都不会越过。 And even if they crossed, what #ifndef GameConfig_h , #define GameConfig_h and #endif GameConfig then for? 即使他们越过,那么#ifndef GameConfig_h#define GameConfig_h#endif GameConfig会做什么呢?

I use VC++ 2010 Express Edition 我使用VC ++ 2010 Express Edition

Include guards help you avoid including the same file more than once from the same translation unit. 包含保护有助于您避免同一翻译单元多次包含同一文件。 However, since the translation units are processed independently, both of them will get the included code, and therefore produce duplicate definitions. 但是,由于翻译单元是独立处理的,因此它们两个都将获得包含的代码,因此会产生重复的定义。

To avoid this problem you need to move definitions out of the header and into a CPP file: 为避免此问题,您需要将定义移出标头并移入CPP文件:

GameConfig.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";

Include guards are only useful inside a single compilation unit (ie one single cpp file). 包含保护仅在单个编译单元 (即单个cpp文件) 内部有用。 Since the cpp files are compiled separately, for each file the include guard will start as undefined and therefore the .h file will be included twice, once for each cpp file. 由于cpp文件是分别编译的,因此对于每个文件,include防护将以未定义形式启动,因此.h文件将被包含两次,每个cpp文件一次。 If the .h file includes for example a function definition, it will be defined twice. 如果.h文件包含例如函数定义,它将被定义两次。

Normally you make the problem "go away" by putting only declarations in the h files, and actually defining the functions in cpp files. 通常,通过仅将声明放在h文件中,并实际上在cpp文件中定义函数,可以使问题“消失”。 That way, the function will only be defined once. 这样,该功能将仅定义一次。

You need to move initialisation of the statics to GameConfig.cpp. 您需要将静态的初始化移动到GameConfig.cpp。

Each source file which includes GameConfig.h is picking up a their own copy of these variables at present. 当前,每个包含GameConfig.h的源文件都将获取这些变量的自己的副本。

The instanciations of your static members shouldn't be in the .h file but in the corresponding .cc file. 静态成员的实例化不应在.h文件中,而应在相应的.cc文件中。

Otherwise they are instantiated in every compilation unit. 否则,它们将在每个编译单元中实例化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM