【发布时间】:2011-06-09 19:26:01
【问题描述】:
在过去的几天里,我一直在试图弄清楚如何为我一直在从事的 CLI 游戏项目链接文件。该项目有两部分,客户端和服务器代码。
客户需要我制作的两个库。第一个是通用游戏板。这在 GameEngine.h 和 GameEngine.cpp 之间进行拆分。头文件看起来像这样
namespace gfdGaming {
// struct sqr_size {
// Index x;
// Index y;
// };
typedef struct { Index x, y; } sqr_size;
const sqr_size sPos = {1, 1};
sqr_size sqr(Index x, Index y);
sqr_size ePos;
class board
{
// Prototypes / declarations for the class
}
}
CPP 文件只是提供所有内容
#include "GameEngine.h"
type gfdGaming::board::functions
客户端还有游戏专用代码(在本例中为井字棋),分为声明和定义(TTT.h、Client.cpp)。 TTT.h 基本上是
#include "GameEngine.h"
#define TTTtar "localhost"
#define TTTport 2886
using namespace gfdGaming;
void* turnHandler(void*);
namespace nsTicTacToe
{
GFDCON gfd;
const char X = 'X';
const char O = 'O';
string MPhostname, mySID;
board TTTboard;
bool PlayerIsX = true, isMyTurn;
char Player = X, Player2 = O;
int recon(string* datHolder = NULL, bool force = false);
void initMP(bool create = false, string hn = TTTtar);
void init();
bool isTie();
int turnPlayer(Index loc, char lSym = Player);
bool checkWin(char sym = Player);
int mainloop();
int mainloopMP();
}; // NS
我决定把它放在一个命名空间中来分组它而不是一个类,因为有些部分在 OOP 中不能很好地工作,而且以后实现起来要容易得多。
我过去在链接客户端时遇到了问题,但此设置似乎有效。
我的服务器也分为两个文件,Server.h 和 Server.cpp。
Server.h 包含:
#include "../TicTacToe/TTT.h" // Server needs a full copy of TicTacToe code
class TTTserv;
struct TTTachievement_requirement {
Index id;
Index loc;
bool inUse;
};
struct TTTachievement_t {
Index id;
bool achieved;
bool AND, inSameGame;
bool inUse;
bool (*lHandler)(TTTserv*);
char mustBeSym;
int mustBePlayer;
string name, description;
TTTachievement_requirement steps[safearray(8*8)];
};
class achievement_core_t : public GfdOogleTech {
public: // May be shifted to private
TTTachievement_t list[safearray(8*8)];
public:
achievement_core_t();
int insert(string name, string d, bool samegame, bool lAnd, int lSteps[8*8], int mbP=0, char mbS=0);
};
struct TTTplayer_t {
Index id;
bool inUse;
string ip, sessionID;
char sym;
int desc;
TTTachievement_t Ding[8*8];
};
struct TTTgame_t {
TTTplayer_t Player[safearray(2)];
TTTplayer_t Spectator;
achievement_core_t achievement_core;
Index cTurn, players;
port_t roomLoc;
bool inGame, Xused, Oused, newEvent;
};
class TTTserv : public gSserver {
TTTgame_t Game;
TTTplayer_t *cPlayer;
port_t conPort;
public:
achievement_core_t *achiev;
thread threads[8];
int parseit(string tDat, string tsIP);
Index conCount;
int parseit(string tDat, int tlUser, TTTplayer_t** retval);
private:
int parseProto(string dat, string sIP);
int parseProto(string dat, int lUser);
int cycleTurn();
void setup(port_t lPort = 0, bool complete = false);
public:
int newEvent;
TTTserv(port_t tlPort = TTTport, bool tcomplete = true);
TTTplayer_t* userDC(Index id, Index force = false);
int sendToPlayers(string dat, bool asMSG = false);
int mainLoop(volatile bool *play);
};
// Other
void* userHandler(void*);
void* handleUser(void*);
在 CPP 文件中,我包含 Server.h 并提供 main() 和之前声明的所有函数的内容。
现在解决手头的问题 链接服务器时遇到问题。更具体地说,对于 nsTicTacToe 中的每个变量(也可能在 gfdGaming 中),我得到一个重复的符号错误。由于我需要井字游戏功能,所以我在构建服务器时链接了 Client.cpp(不带 main())
ld: duplicate symbol nsTicTacToe::PlayerIsX in Client.o and Server.o
collect2: ld returned 1 exit status
Command /Developer/usr/bin/g++-4.2 failed with exit code 1
It stops once a problem is encountered, but if PlayerIsX is removed / changed temporarily than another variable causes an error
基本上,我正在寻找有关如何更好地组织我的代码以希望修复这些错误的任何建议。
免责声明: -如果我提供的信息太多或太少,我提前道歉,因为这是我第一次发帖
-我尝试使用 static 和 extern 来解决这些问题,但显然这些不是我需要的
感谢所有花时间阅读所有内容并回复的人 =)
【问题讨论】:
-
尝试使用标题保护,你没有使用任何。
-
我在下面提供了一个答案,但也请像其他评论者指出的那样使用标题保护。
-
由于他在 LINKING 时遇到问题,头球后卫可能不是他唯一的问题,尽管使用它们总是比不使用更好(我认为?)。
-
在你的头文件中,你通常有像 void DoWork(); 这样的前向声明。如果你有一个函数体的实现,比如 void DoWork() { /* 你的代码在这里...*/ },并且这个头文件包含在一些 cpp 文件中,那么你的链接器有问题。为此,您可以实现一个 cpp 文件并将 DoWork 函数体排除在其中。我们在各个领域也遇到了类似的问题。要解决它,请移动 cpp 文件中的字段声明。当你在其他文件中需要它时,请参阅 maxelost 的解决方案
标签: c++ linker namespace-organisation