(C++) Linking with namespaces causes duplicate symbol error - c++

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.
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
}
}
And the CPP file is just giving everything content
#include "GameEngine.h"
type gfdGaming::board::functions
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
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.
My server is also split into two files, Server.h and Server.cpp.
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*);
And in the CPP file I include Server.h and provide main() and the contents of all functions previously declared.
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
Essentially, I am looking for any advice on how to better organize my code to hopefully fix these errors.
Disclaimers:
-I apologize in advance if I provided too much or too little information, as it is my first time posting
-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 =)

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.
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).
In TTT.h:
namespace nsTicTacToe {
...
extern bool PlayerIsX;
...
}
In TTT.cpp:
#include "TTT.h"
bool nsTicTacToe::PlayerIsX;
and so on for the other definitions.
By the way, remember to have proper guard #ifdefs:
#ifndef __TTT_H
#define __TTT_H
... header contents
#endif // __TTT_H

Actually, extern IS what you need. You're probably just not realizing or remembering that you'll also have to define such variables in a cpp file.
header:
extern int somevar;
source:
int somevar = ?;
By putting all of your globals in the header you're making copies of them everywhere you include them, which is exactly what your compiler is bitching about.

You are essentially using globals, which is strongly not recommended in C++, but is sometimes necessary in C.
You could get it working with extern, but the "better" answer would be to wrap your globals in a state object of some sort.
struct State
{
GFDCON gfd;
const char X;
const char O;
string MPhostname, mySID;
board TTTboard;
bool PlayerIsX, isMyTurn;
char Player, Player2;
};
Create your state object in Main and pass it to each function that needs to know the state of the game system.
This will lead to much better code organization in the long run.

you could put the namespace nsTicTacToe part into it's own .cpp file, compile it separately and link it in.
You might also need a header file which just declares externs for the variables, and include that in you client and server .cpp files.

Related

C++ Program cannot compile properly using CMD howerever complies within VSC

A program im writing successfully runs on the IDE visual studio code. However, when attempting to use the Bitvise SSH client to run my program I get a list of errors that I myself cannot understand the problem for. Bitvise it another way to access the CMD client from a remote server, for all intenstive purposes it acts the same as windows CMD. I will provide a screen cap of the errors and a full run down of the parts of my program that I believe are causing the errors. If any further code is required please feel free to ask.
errors screen cap
This error report shows a common error, with something being a placeholder for all instances.
multiple definition of `something' /tmp/ccBhjFYn.o:(.bss+0x0): first defined here
This error DOES NOT happen in visual studio code
From this error report it can be seen the issue is found within driver.cpp and my header.h file. For this reason i wont provide a minimal code for these files, but they are small enough to not require one.
MAIN
int main()
{
Customer c;
Part p;
Builder b;
const string fileName = "Parts.txt";
auto partsVec = readpartFile();
auto customerVec = readcustomerFile();
auto builderVec = readbuilderFile();
fexists(fileName);
complexity(c, partsVec);
robotComplexity(partsVec,customerVec);
writeFile(buildAttempt(b, complexity(c, partsVec), variability(customerVec, builderVec)));
return 0;
}
HEADER FILE
#include <vector>
#include <string>
struct Customer {
std::string customerName;
std::string projectName;
std::string listofParts;
} myCustomer;
struct Part {
char partCode;
std::string partName;
int maximum;
int minimum;
int complexity;
} myPart;
struct Builder {
std::string builderName;
int ability;
int variability;
} myBuilder;
bool fexists(const std::string filename);
std::vector<Part> readpartFile();
std::vector<Customer> readcustomerFile();
std::vector<Builder> readbuilderFile();
float complexity(const Customer& c, const std::vector<Part>& parts);
void robotComplexity(const std::vector<Part>& vecB, const std::vector<Customer>& vecC);
double variability(const std::vector<Customer>& customerList, const std::vector<Builder>& builderList);
std::vector<double> buildAttempt(Builder b, double variaiblity, double complexityRobot);
void writeFile(std::vector<double> build);
Thankyou for any help. This question may be hard to understand and follow but i did try my best. Any sugguestions to help improve this question are welcome but please be friendly :)
This in header.h
struct Customer {
std::string customerName;
std::string projectName;
std::string listofParts;
} myCustomer;
Is a definiton of a global variable myCustomer. As such it does not belong in a header file.
Change the header file to this
struct Customer {
std::string customerName;
std::string projectName;
std::string listofParts;
};
extern Customer myCustomer; // global variable declaration
Then to one of your cpp files (I suggest implementation.cpp) add this
Customer myCustomer; // global variable definition
Or you could just do away with global variables completely (the best solution).
NOTE in some of my comments above, I said you have global variable declarations in your header file. What I meant was you have global variable definitions in your header file. The difference between a definition and a declaration is what is crucial here. It's fine to put declarations in a header file, it's wrong to put a definition. Sorry for any confusion.

"Expected Class name" Error for Inheritance

Problem
Currently designing a GUI game, and I've finished the basic OOP aspects of the game(along with 90% of all non-abstract classes). However, I tried extending a class called Protester to this class which caused the error at line 5 here:
#ifndef HardcoreProtester_h
#define HardcoreProtester_h
#include "Protester.h"
class HardcoreProtester : public Protester{
public:
HardcoreProtester(StudentWorld* w, int x, int y) : Protester(w, x, y, IID_HARD_CORE_PROTESTER, 20){};
private:
};
#endif /* HardcoreProtester_h */
when extending from this
#ifndef Protester_h
#define Protester_h
#include "Actor.h"
#include "StudentWorld.h"
class Protester : public Human{
static const int INIT_PERP_TICK = 200;
static const int DAMAGE = 20;
static const int SHOUT_WAIT = 25;
static const int MIN_STEP = 8;
static const int MAX_STEP = 60;
static const int EXIT_X = 60;
static const int EXIT_Y = 60;
public:
static const int INIT_HITPOINTS = 5;
Protester(StudentWorld* w, int startX, int startY, int ID, int hp);
virtual ~Protester();
virtual void doSomething();
Direction pickRandomDirection();
virtual bool changeState(Direction dir);
virtual bool isDead() const{
return Human::isDead() && getX() == 60 && getY() == 60;
}
virtual bool isDeadState() const{
return Human::isDead();
}
virtual void consume();
virtual void setDead();
virtual bool moveDelta(StudentWorld* world, Direction dir, int& xdir, int& ydir, int steps = 1);
int determineRandomSteps();
bool canTurn(Actor::Direction dir);
Actor::Direction randTurn(Actor::Direction dir);
Actor::Direction oppositeDir(Actor::Direction dir);
Actor::Direction numToDir(int num);
private:
int step;
int restTick;
int shoutTick;
int perpTick;
};
#endif /* Protester_h */
I've looked on stack overflow for answers to why the error persists, and I've tried to break a nonexistent circular dependency (as you can see Protester does not even include HardcoreProtester). I tried to break any circular dependency by adding a
class Protester;
above the definition of HardcoreProtester.
However, this gives me the error:
Type 'Protester' is not a direct or virtual base of 'HardcoreProtester'
and
Base class has incomplete type
I also made sure the base class is not abstract(I was able to initialize it without any errors).
If this isn't enough information, here's the github for the project:
https://github.com/OneRaynyDay/FrackMan
I apologize for any ambiguity in my question - I just simply have no idea where the error could be(hence an attempt for MCVE with github link). Thanks in advance!
EDIT: Also, using XCode to make this project. By this point into debugging I'm starting to suspect XCode of being the culprit.
In addition, just to be extra helpful and verifiable, here's a picture of the error diagnosis from XCode:
No, XCode is not the culprit. It's not XCode's fault that you have circular header dependencies.
According to the compiler dump you posted, it appears that your StudentWorld.h header file has a #include of HardProtester.h.
This is a case of classical circular header dependencies.
First, you are including Protester.h.
Before Protester.h even gets to its definition of the Protester class, it has an #include of StudentWorld.h.
StudentWorld.h must have an #include of HardProtester.h, according to your compiler's error diagnostics.
Now, your HardProtester.h has it's own include of Protester.h. But, because its ifndef/define guard has already been set, in the first include of Protester.h, the second #include of this header file becomes empty text.
And now, upon returning to HardProtester.h, you attempt to declare it's class.
Now, if you have been paying attention carefully, you should've figured out that the Protester class has not yet been declared, yet this header file attempts to declare its subclass.
There's your problem. You need to completely refactor how your header files depend on each other, to eliminate this circular dependency. Merely sticking a "class Protester" in HardProtester.h is insufficient. The entire class must be defined, not just declared, before you can declare any subclasses.
You have a circular dependency between Protester.h and StudentWorld.h
Try fixing that and see if it helps.

How to make a variable available to multiple .cpp files using a class?

This question has derived from this one.
I have a working program which must be split into multiple parts. In this program is needed to use a variable (now it's a GTK+ one :P) many times in parts of the program that will end up in separated .cpp files.
So, I made a simple example to understand how to make variables available to the program parts. A modified version of the previous code would be:
#include <iostream>
using namespace std;
int entero = 10;
void function()
{
cout<<entero<<endl;
//action1...;
}
void separated_function()
{
cout<<entero<<endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
It is needed to split the code correctly, to have function(), another_function() and main() in separated .cpp files,and make entero avaliable to all of them... BUT:
In the previous question #NeilKirk commented:Do not use global variables. Put the required state into a struct or class, and pass it to functions as necessary as a parameter (And I also have found many web pages pointing that is not recommended to use global variables).
And, as far I can understand, in the answer provided by #PaulH., he is describing how to make variables avaliable by making them global.
This answer was very useful, it worked fine not only with char arrays, but also with ints, strings and GTK+ variables (or pointers to variables :P).
But since this method is not recommended, I would thank anyone who could show what would be the correct way to split the code passing the variables as a function parameter or some other method more recommended than the - working - global variables one.
I researched about parameters and classes, but I'm a newbie, and I messed the code up with no good result.
You need to give the parameter as a reference if you want the same comportement as a global variable
#include <iostream>
using namespace std;
// renamed the parameter to avoid confusion ('entero' is valid though)
void function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value
//action1...;
}
void separated_function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value again
//action2...;
}
int main( int argc, char *argv[] )
{
int entero = 10; // initializing the variable
// give the parameter by reference => the functions will be able to modify its value
function(entero);
separated_function(entero);
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
output:
10
11
12
Defining a class or struct in a header file is the way to go, then include the header file in all source files that needs the classes or structures. You can also place function prototypes or preprocessor macros in header files if they are needed by multiple source files, as well as variable declarations (e.g. extern int some_int_var;) and namespace declarations.
You will not get multiple definition errors from defining the classes, because classes is a concept for the compiler to handle, classes themselves are never passed on for the linker where multiple definition errors occurs.
Lets take a simple example, with one header file and two source files.
First the header file, e.g. myheader.h:
#ifndef MYHEADER_H
#define MYHEADER_H
// The above is called include guards (https://en.wikipedia.org/wiki/Include_guard)
// and are used to protect the header file from being included
// by the same source file twice
// Define a namespace
namespace foo
{
// Define a class
class my_class
{
public:
my_class(int val)
: value_(val)
{}
int get_value() const
{
return value_;
}
void set_value(const int val)
{
value_ = val;
}
private:
int value_;
};
// Declare a function prototype
void bar(my_class& v);
}
#endif // MYHEADER_H
The above header file defines a namespace foo and in the namespace a class my_class and a function bar.
(The namespace is strictly not necessary for a simple program like this, but for larger projects it becomes more needed.)
Then the first source file, e.g. main.cpp:
#include <iostream>
#include "myheader.h" // Include our own header file
int main()
{
using namespace foo;
my_class my_object(123); // Create an instance of the class
bar(my_object); // Call the function
std::cout << "In main(), value is " << my_object.get_value() << '\n';
// All done
}
And finally the second source file, e.g. bar.cpp:
#include <iostream>
#include "myheader.h"
void foo::bar(foo::my_class& val)
{
std::cout << "In foo::bar(), value is " << val.get_value() << '\n';
val.set_value(456);
}
Put all three files in the same project, and build. You should now get an executable program that outputs
In foo::bar(), value is 123
In main(), value is 456
I prefer to provide a functional interface to global data.
.h file:
extern int get_entero();
extern void set_entero(int v);
.cpp file:
static int entero = 10;
int get_entero()
{
return entero;
}
void set_entero(int v)
{
entero = v;
}
Then, everywhere else, use those functions.
#include "the_h_file"
void function()
{
cout << get_entero() << endl;
//action1...;
}
void separated_function()
{
cout << get_entero() << endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<< get_entero() <<endl;
//something else with the mentioned variables...;
return 0;
}
If you do not plan to modify the variable, it is generally ok to make it global. However, it is best to declare it with the const keyword to signal the compiler that it should not be modified, like so:
const int ENTERO = 10;
If you are using multiple cpp files, also consider using a header file for your structures and function declarations.
If you are planning on modifying the variable, just pass it around in function parameters.

multiple definition of class

first of all I know that this question has been answered very often, but the answers didn't help me a lot...
That is the code which is causing the error.
#include "WayFinderClass.h"
WayFinderClass::WayFinderClass(int NavigationMapIndex) { ... };
int WayFinderClass::TotalNumberOfPoints(int point[100][100][2]) { ... };
int WayFinderClass::ConnectedWithXPoints(int point[100][100][2], int pointID) { ... };
void WayFinderClass::findWay(int start, int goal) { ... };
WayFinderClass.h :
#ifndef WAYFINDERCLASS_H_INCLUDED
#define WAYFINDERCLASS_H_INCLUDED
#include "NavigationMap.h"
class WayFinderClass {
public:
int finalWay[100];
int start;
int goal;
int alreadyCheckedInt[100];
void findWay(int start, int goal);
WayFinderClass(int NavigationMapIndex);
private:
int pointConnectedWith[100];
int wayProgress[100][100];
int numberOfPoints;
bool antsInProgress[100];
int TotalNumberOfPoints(int point[100][100][2]);
int ConnectedWithXPoints(int point[100][100][2], int pointID);
NewNavigationMap NavigationMap;
};
#endif // WAYFINDER_H_INCLUDED
And that is the error I get:
C:\{...} Line 3 multiple definition of 'WayFinderClass::WayFinderClass(int)'
So what am I supposed to do? I already tried to include the .h file but it didn't help me.
I also checked every other file whether the file WayFinderClass.cpp has been included a second time - but I found nothing.
You should not include source files (.cpp). Include headers instead.
Your problem was probably caused by including the source file in main.cpp as you said and then compiling it separately as well. In that case, functions defined in WayFinderClass.cpp would be defined again in main due to the inclusion and you can't have more than one definition for a function.

Static Functions in C++

I've read a few posts on here about static functions, but still am running into trouble with implementation.
I'm writing a hardcoded example of Dijkstra's algorithm for finding the shortest path.
Declared in Alg.h:
static void dijkstra();
Defined in Alg.cpp:
static void Alg::dijkstra() {
//Create Map
Initialize();
//Loop to pass through grid multiple times
for(int i=0; i<5; i++)
{
current=1;
while(current!=6)
{
//Iterate through and update distances/predecessors
//For loop to go through columns, while current iterates rows
for(int j=1; j<7; j++)
{
//Check if distance from current to this node is less than
//distance already stored in d[j] + weight of edge
if(distanceArray[current][j]+d[current]<d[j])
{
//Update distance
d[j] = distanceArray[current][j]+d[current];
//Update predecessor
p[j] = current;
}
}
//Go to next row in distanceArray[][]
current++;
} //End while
} //End for
output();
} //End Dijkstras
I want to call my function from main without an object. When I had all of this code in Main.cpp, it worked perfectly. Splitting it up into separate files caused the error Main.cpp:15: error: ‘dijkstra’ was not declared in this scope.The posts I came across when searching SE gave me me the impression that to do this, I needed to make that method static, yet I still have no luck.
What am I doing wrong?
Main.cpp:
#include <iostream>
#include "Alg.h"
int main() {
dijkstra();
return 0;
}
Edit: Added full header file, Alg.h:
#ifndef Alg_
#define Alg_
#include <iostream>
#include <stack>
using namespace std;
class Alg
{
public:
void tracePath(int x);
void output();
void printArray();
void Initialize();
static void dijkstra();
int current, mindex;
int distanceArray[7][7]; //2D array to hold the distances from each point to all others
int d[6]; //Single distance array from source to points
int p[6]; //Array to keep predecessors
int copyD[6]; //Copy of d[] used for sorting purposes in tracePath()
int order[6]; //Contains the order of the nodes path lengths in ascending order
}; //End alg class
#endif
Original all-in-one working Main.cpp file: http://pastebin.com/67u9hGsL
You should call it this way:
Alg::dijkstra();
Limitations
Can't call any other class functions that are not static.
Can't access non static class data members.
Can instantiate an object via new class() when constructor is private/protected. E.g. a factory function.
You can just use a namespace instead of having a class with all static members.
Alg.h:
namespace Alg
{
void dijkstra();
}
and in Alg.cpp
namespace Alg
{
void dijkstra()
{
// ... your code
}
}
in main.cpp
#include "Alg.h"
int argc, char **argv)
{
Alg::dijkstra();
return 1;
}
Are you sure the function is supposed to be static?
It looks as if you want just a function?
in your header file:
#ifndef DIJKSTRA_H
#define DIJKSTRA_H
void dijkstra();
#endif
in your cpp file
void dijkstra() {
/* do something */
}
in your main file:
#include "yourcppfile.h"
int main(int argc, char **argv) {
dijkstra();
}
if you really want a static function you have to put it into a nested class:
class Alg {
public:
static void dijkstra();
/* some other class related stuff */
}
the implementation somewhere in a cpp file
void Alg::dijkstra() {
/* your code here */
}
and then in your cpp file where the main resides
#include "your header file.h"
int main(int argc, char **argv) {
Alg::dijkstra();
}
If I remember right any 'static' function is limited to the module in which it is implemented. So, 'static' prevents using the function in another module.
In your header file Alg.h:
#ifndef __ALG_H__
#define __ALG_H__
namespace Alg {
void dijkstra();
}
#endif
The include guards are necessary if you plan to include the header in more than one of your cpp files. It seems you would like to put the function in a namespace Alg, right?
In Alg.cpp:
#include "Alg.h"
void Alg::dijkstra() { /* your implementation here */ }
Then, in main.cpp you call it with full namespace qualification:
#include "Alg.h"
int main() {
Alg::dijkstra();
}
If you just want to distribute your code over several files, I don't see why the function should be declared static.
You are confusing the 'static' keyword for local functions, with the 'static' keyword used in a class to make a function a class function and not an object function.
Remove static the first line of Alg.cpp and in the header file. This will allow Alg.o to contain global symbols that main can refer to and the linker can link.
You still need to call Alg::dijkstra() as was stated by #egur.
After this you may still get errors. The way you are using Alg:: is more like a namespace than a 'class' definition.
Now that we have the complete declaration of your class Arg, it feels like the singleton design pattern could be useful:
http://en.wikipedia.org/wiki/Singleton_pattern
The key here is the ‘dijkstra’ was not declared in this scope error.
Take your all-in-one source file and remove the main function. Make a new source file with this in it:
void dijkstra();
void output();
int main(int argc, char *argv[]) {
dijkstra();
output();
return 0;
}
The all-in-one cpp without a main plus this file above should compile together and give you the same result as before with one source, as it does for me. You will get a duplicate symbol _main error if you forgot to remove the main from the algorithm file.
No static needed.
My answer here fails to touch on good practices on header files, that is, you would want to include those function declarations in a .h file. It solves the compile-time error though.
You may want to find a good book to help you through some of the machinery of C++, where program context (in a linguistic sense) can change the meaning of keywords. This can be bewildering, and it proves to be exactly that for a language with as much colorful history as C++. Take a look here for book suggestions.