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
Вам нужно переместить инициализацию статики в GameConfig.cpp.
Каждый исходный файл, который включает в себя GameConfig.h, в настоящее время собирает собственную копию этих переменных.
Защитные ограждения помогают избежать многократного включения одного и того же файла из одного и того же блока перевода. Однако, поскольку блоки перевода обрабатываются независимо, оба они получат включенный код и, следовательно, создадут дубликаты определений.
Чтобы избежать этой проблемы, вам нужно переместить определения из заголовка в файл 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";
Экземпляры ваших статических членов должны быть не в файле .h, а в соответствующем файле .cc.
В противном случае они создаются в каждой единице компиляции.
Включить охрану полезно только внутри одного модуля компиляции (т.е. один единственный файл cpp). Так как файлы cpp компилируются отдельно, для каждого файла защита включения запускается как неопределенная, и поэтому файл .h будет включен дважды, один раз для каждого файла cpp. Если файл .h содержит, например, определение функции, он будет определен дважды.
Обычно вы заставляете проблему «уходить», помещая только объявления в h-файлы и фактически определяя функции в cpp-файлах. Таким образом, функция будет определена только один раз.