(C ++)与名称空间的链接导致重复的符号错误 [英] (C++) Linking with namespaces causes duplicate symbol error

查看:93
本文介绍了(C ++)与名称空间的链接导致重复的符号错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在过去的几天中,我一直在尝试找出如何链接我一直在从事的CLI游戏项目的文件.该项目分为两部分,即客户端代码和服务器代码.

For the past few days, I have been trying to figure out how to link the files for a CLI gaming project I have been working on. There are two halves of the project, the Client and the Server code.

客户端需要我创建的两个库.第一个是通用游戏板.这在GameEngine.h和GameEngine.cpp之间分配.头文件看起来像这样

The client needs two libraries I've made. The first is a general purpose game board. This is split between GameEngine.h and GameEngine.cpp. The header file looks something like this

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文件只是提供了所有内容

And the CPP file is just giving everything content

#include "GameEngine.h"

type gfdGaming::board::functions

客户端还具有特定于游戏的代码(在本例中为TicTacToe),该代码分为声明和定义(TTT.h,Client.cpp). TTT.h基本上是

The client also has game-specific code (in this case, TicTacToe) split into declarations and definitions (TTT.h, Client.cpp). TTT.h is basically

#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中无法正常工作,并且以后实现起来要容易得多.

I made the decision to put this in a namespace to group it instead of a class because there are some parts that would not work well in OOP, and it's much easier to implement later on.

过去我在链接客户端时遇到麻烦,但是此设置似乎可以正常工作.

I have had trouble linking the client in the past, but this setup seems to work.

我的服务器也分为两个文件,Server.h和Server.cpp.

My server is also split into two files, Server.h and Server.cpp.

Server.h完全包含:

Server.h contains exactly:

#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()和先前声明的所有函数的内容.

And in the CPP file I include Server.h and provide main() and the contents of all functions previously declared.

现在遇到了问题 链接服务器时出现问题.更具体地说,对于nsTicTacToe中的每个变量(还有可能在gfdGaming中),我都会得到重复的符号错误.由于我需要TicTacToe函数,因此在构建服务器时会链接Client.cpp(不带main())

Now to the problem at hand I am having issues when linking my server. More specifically, I get a duplicate symbol error for every variable in nsTicTacToe (and possibly in gfdGaming as well). Since I need the TicTacToe functions, I link Client.cpp ( without main() ) when building the server

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

本质上,我正在寻找有关如何更好地组织我的代码以有望解决这些错误的建议.

免责声明: -如果我提供的信息太多或太少,我事先表示歉意,因为这是我第一次发布

Disclaimers: -I apologize in advance if I provided too much or too little information, as it is my first time posting

-我曾尝试使用static和extern来解决这些问题,但显然这些不是我所需要的

-I have tried using static and extern to fix these problems, but apparently those are not what I need

感谢所有花时间阅读所有内容并回复=)的人

Thank you to anyone who takes the time to read all of this and respond =)

推荐答案

您会得到有关重复定义的错误,因为这就是您所拥有的:每次.cpp文件包含TTT.h时,都会定义一个全局bool PlayerIsX(在nsTicTacToe命名空间,但仍是全局的).在这种情况下,其中包含了Server.cpp和Client.cpp.

You get error about duplicate definitions because that's what you have: each time a .cpp file includes TTT.h, a global bool PlayerIsX is defined (in the nsTicTacToe namespace, but still global). In this case, it's Server.cpp and Client.cpp that are including it.

解决此问题的一种方法是使用extern将定义更改为声明,然后在相应的.cpp文件(例如TTT.cpp)中进行实际定义.

One way to solve this could be to change the definitions into declarations by using extern, then doing the actual definition in a corresponding .cpp file (TTT.cpp, for instance).

在TTT.h中:

namespace nsTicTacToe {
   ...
   extern bool PlayerIsX;
   ...
}

在TTT.cpp中:

#include "TTT.h"

bool nsTicTacToe::PlayerIsX;

以此类推,以获取其他定义.

and so on for the other definitions.

顺便说一句,记住要有适当的后卫#ifdef s:

By the way, remember to have proper guard #ifdefs:

#ifndef __TTT_H
#define __TTT_H
... header contents
#endif   // __TTT_H

这篇关于(C ++)与名称空间的链接导致重复的符号错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆