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
答案 0 :(得分:2)
包含警卫可帮助您避免在同一翻译单元中多次包含同一文件。但是,由于翻译单元是独立处理的,因此它们都将获得包含的代码,因此产生重复的定义。
要避免此问题,您需要将定义移出标题并进入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";
答案 1 :(得分:1)
包含防护仅在单个编译单元中有用(即一个单独的cpp文件)。由于cpp文件是单独编译的,因此对于每个文件,include guard将以未定义的方式启动,因此.h文件将包含两次,每个cpp文件一次。如果.h文件包含例如函数定义,则它将被定义两次。
通常,只通过在h文件中放入声明,并实际定义cpp文件中的函数,就可以使问题“消失”。这样,该函数只会被定义一次。
答案 2 :(得分:1)
您需要将静态初始化移至GameConfig.cpp。
目前,每个包含GameConfig.h的源文件都会获取这些变量的副本。
答案 3 :(得分:1)
静态成员的实例不应该在.h文件中,而应在相应的.cc文件中。
否则它们将在每个编译单元中实例化。