Problems with pointer to a class - c++

I have defined my own class in a Qt project that gives me problems, but I think this could be general C++.
When I try to declare a pointer to my class in any include file in the project myHashMap like
myHashMap* map;
the compiler gives the error and say "multiple definition of map". What is this? I didn't even define a pointer even, just declared one.
However, putting myHashMap* map in a source file doesn't give any errors.
Here is the class definition and declaration, sorry that it looks a bit messy.
#include QObject
#include QHash
class myHashMap : public QObject
{
Q_OBJECT
public:
explicit myHashMap(QObject *parent = 0);
float Get(const QString& key) const;
void setValue(const char key, float value)
{
// only emit value changed if the value has actually changed
//if( hash->value(key) != value)
//{
hash->insert(key,value);
//emit ValueChanged(key, value);
//}
}
signals:
public slots:
//void ValueChanged(const char& key, float newValue);
private:
QHash<const char, float>* hash;
};
myHashMap::myHashMap(QObject *parent) :
QObject(parent)
{
hash = new QHash<const char,float>;
}
EDIT:
Aaa, bummer, I just forgot to prepend MyHashMap* with the extern keyword. Programming C++ is a nitty-gritty. Wouldn't it make sense if the compiler sent a warning here, like "hello there, you now got multiple definitions in a few headers, forgot an extern keyword?" ?
However, I got a new problem.
In "communication.h" I have declared a namespace like this
namespace reference
{
extern const char potentiometer;
extern const char KpAngle;
extern const char KiAngle;
extern const char KdAngle;
extern const int length;
extern myHashMap* hmap;
void init();
}
In the communication.cpp I want to use *hmap like below, but the compiler returns "undefined reference to hmap". Yet I have included the "communication.h" both in "communication.cpp" and in the *.pro file. See the code below:
#include "communication.h"
namespace reference
{
const char potentiometer = 0x05;
const char KpAngle = 0x06;
const char KiAngle = 0x07;
const char KdAngle = 0x08;
const int length =1;
//QList<const char>* summary = new QList<const char>();
void init()
{
//using namespace reference;
//#include "communication.h"
//myHashMap* hmap = new myHashMap();
//when using this a hmap is created, however setValue returns undefined ref
//Both methods below returns "undefine reference to hmap". Same if i try "using namespace"
//reference::hmap = new myHashMap();
//hmap = new myHashMap();
/*
reference::hmap->setValue(potentiometer,-1);
reference::hmap->setValue(KpAngle,-1);
reference::hmap->setValue(KiAngle,-1);
reference::hmap->setValue(KdAngle,-1);*/
}
}
EDIT: Above a pointer to hmap is only declared, not defined. I therefore had do define hmap by putting
myHashMap* hmap directly in the reference scope in "communication.cpp". Now it works.

Prefix the declaration with extern in your header file; i.e.:
extern myHashMap* map;
You will also need to put the variable definition (without extern) into a source file somewhere.
The reason this causes a problem is because header files are typically included by multiple source files. Each source file is compiled in its own translation unit, independently of all the other ones. If you put a variable declaration in a header file, then you'll get multiple translation units all trying to define the same variable, causing a conflict.
What you want is for the variable to exist only within a single translation unit, hence the declaration in one source file. The extern version just indicates that there is (or will be) a variable with that name and type, but it doesn't actually cause it to be created. It effectively just makes it visible to anything which sees it.

It is likely that the name "map" is already reserved by another variable or function in a library you are using.Also if you include the header in other headers that are all included in your main file you can get this error.

Related

I am getting an error of redefinition while using extern header file

I am getting an error of redefinition while using extern, but I was also told, that extern variable should be used like this, why I am getting this error and how should I use extern in this case so it will work? (I can use this variable even if I don't specify it in Tab.cpp, but I am getting error of finding one or more symbols, which was defined 2 times.)
Files:
Tab.h:
#pragma once
#include "wx/wx.h"
class Tab : public wxFrame {
wxDECLARE_EVENT_TABLE();
void close(wxCommandEvent& evt);
void init();
public:
Tab();
};
Tab.cpp:
#include "Tab.h"
#include "ids.h"
#include "wx/wx.h"
int maxid;
wxBEGIN_EVENT_TABLE(Tab, wxFrame)
EVT_BUTTON(2, Tab::close)
wxEND_EVENT_TABLE()
Tab::Tab() : wxFrame(nullptr, maxid++, "ERIS 2") {
init();
}
void Tab::close(wxCommandEvent &evt) { this->Close(); evt.Skip(); }
void Tab::init() {
wxGridSizer* sizer = new wxGridSizer(10, 10, 0, 0);
for(int x = 0; x < 10; ++x)
for(int y = 0; y < 10; ++y) {
sizer->Add(new wxButton(this, maxid, _(std::to_string(maxid))), wxEXPAND | wxALL);
++maxid;
}
this->SetSizer(sizer);
sizer->Layout();
}
ids.cpp:
#include "ids.h"
std::vector<Object> ids;
Object& search(const char* name) {
for(std::vector<Object>::iterator it = ids.begin(); it != ids.end(); *++it)
if((*it).name == name)
return *it;
}
Object& search(int id) {
for(std::vector<Object>::iterator it = ids.begin(); it != ids.end(); *++it)
if((*it).id == id)
return *it;
}
void add(Object& obj) {
ids.emplace_back(obj);
}
ids.h:
#pragma once
#include <vector>
#include "wx/wx.h"
struct Object {
wxObject* obj;
const char* name;
int id;
};
Object& search(const char*);
Object& search(int);
void add(Object&);
extern std::vector<Object> ids;
extern int maxid = 0;
The line
extern int maxid = 0;
in the file ids.h is a definition, because it also initializes the variable. Instead, it should only contain a declaration:
extern int maxid;
The definition should be in a source file (.cpp), not a header file (.h). Header files should only contain declarations of variables, not definitions. Otherwise, you will violate the one definition rule if you include the header file more than once, or if you already have a definition in a source file.
In your case, you already have a definition of the variable in the file Tab.cpp. The line int maxid; is a definition, because it is not using the extern keyword. If you want to initialize the variable, you should do it in that file.
There are definitions and declarations. A declaration tells the compiler that something exists. A definition is a declaration that has all the information needed to describe that thing.
For global variables like maxid, The extern says that it will have external linkage; that is, be known to the linker and be seen between different source files (translation units).
Many different translation units can say extern int maxid; and they all just say "OK, I know about this symbol, I'll find it somewhere eventually.". So, that's fine to put in a header which becomes part of more than one translation unit.
However, when you give it an initializer, in this case the =0 (one of several possible ways describe initialization), then it becomes a definition. It causes storage to be allocated and a definite location set up for that variable. You should not do that in a header, because each file that includes it will define the same variable. Thus, at link time you get more than one, which is an error.
The legacy way of doing this is to put extern int x; in the header so that everyone knows x exists, and then put int x = 0; in one CPP file so that this variable lives somewhere. Writing extern int x = 0; would mean the same thing but is un-idiomatic.
The modern way to handle this is to use a feature created for this express purpose. Put inline int x = 0; in the header file. This will define it in every translation unit that includes it, but they will be marked such that the linker understands that they are all the same and it should just pick one and ignore the others.
extern int maxid = 0; When you assign something, this is a definition and extern becomes meanless and ignored. Remove the assignment:
extern int maxid;
You have the definition in Tab.cpp and it's assigned to zero by default as a global variable.

Cannot Compile .cpp File When Trying To Define Private Var

I am attempting to compile a .cpp file that includes a .h file and then implements the class outlined.
In String.h:
using namespace std;
class String
{
private:
int _length;
char *data;
int getCharArraySize(char arr[]);
In String.cpp:
#include "String.h"
using namespace std;
/*
* Private vars and methods
*/
int String::_length;
char String::*data;
int String::getCharArraySize(char arr[])
{
//method body
return 0;
}
When I attempt to compile with g++ I get this error:
% g++ String.cpp -c
String.cpp:14:17: error: ‘int String::_length’ is not a static data member of ‘class String’
int String::_length;
I am only having issues with String::_length. I was initially thinking that it was due to _length being private but all the other private methods/vars, compile just fine. I also need to leave this .h file as is so I cannot just make it public. Any help would be appreciated!
Well, it's exactly as the compiler says: _length is not a static member variable. Yet, you are treating it as one by providing it with its own definition. Simply do not do that. Only static member variables should be defined like that.
The same goes for data.
By the way, if you do ever have to define a char* variable, then this is wrong:
char String::*data;
and this is right:
char* String::data;
Lexical grammar production oddities (inherited from C) notwithstanding, the * is part of the type, not the name.

C++: Defining void* array in header file and declaring it in a cpp file?

I saw this question and I tried to do as the answer to that question said. To use the extern keyword in the header file to define an array and then declare it outside of that namespace or class in a other cpp file.
It didn't work for me really, I'm not sure if it because I'm using a void pointer array (i.e void* array[]) or if it's just my ignorance that prevents me from seeing the problem.
This is the shortest example I can come up with:
[cpp.cpp]
#include "h.h"
void main(){
void* a::b[] = {
a::c = a::d(1)
};
}
[h.h]
namespace a{
struct T* c;
struct T* d(int e);
extern void* b[];
}
So the problem is that I receive the error:
IntelliSense: variable "a::b" cannot be defined in the current scope
And I have no clue why that is.
First, you should declare main() as int ! See here why.
Declaring your array as extern in a namespace means that it belongs to the namespace but is defined somewhere ele, normally in a separate compilation unit.
Unfortunately, in your main(), you try to redefine the element as a local variable. This explains the error message you receive.
You shoud do as follows:
#include "h.h"
void* a::b[] { a::c, a::d(1) }; // global variable belonging to namespace
int main() // int!!!
{
/* your code here */
}
The code will compile. The fact that a::b[] is defined in the same compiling unit is accepted. But the linker will complain because a::d(1) is a call to the function d returning a pointer to a struct, and this function is defined nowhere.
Therfore you should also define this:
namespace a {
struct T* d(int e)
{
return nullptr; // in reality you should return a pointer to struct T
}
}
Interestingly, struct T does not need to work for this code to compile and link.

Defining static const variable in C++

I have a class like this:
/* ClassA.h */
class ClassA{
public:
static const size_t SIZE = 10;
int array[SIZE];
funcA();
funcB();
...
};
And, in the other cpp file, there is code like:
min(ClassA::SIZE, other_variable);
But, I cannot build this code, and I get an error like below (in latest cc in Mac OS X, Apple LLVM 4.2 (clang-425.0.28))
Undefined symbols "ClassA::SIZE" ...
It is probably because "SIZE" is defined within the header file and can be used like a macro, ClassA.o does not contain "SIZE" as symbol. At the same time, referring code somehow requires symbol when used inside "min" template. (I can check it by 'nm' command that ClassA.o does not contains "SIZE" symbol, but referring code's object file contains "SIZE" symbol.)
ClassA.o can contains "SIZE" symbol by defining literal number in ClassA.cpp like below:
const int ClassA::SIZE = 10;
But in this case, there is another error like below, due to an array being defined in header file.
error: fields must have a constant size: 'variable length array in structure' extension will never be supported
The original code worked in some older complier (LLVM 4.0).
Any good idea to solve this situation?
You need to provide a definition for ClassA::SIZE, but still give the constant integral value at the point of declaration:
/* ClassA.h */
class ClassA{
public:
static const size_t SIZE = 10; // value here
int array[SIZE];
funcA();
funcB();
...
};
/* ClassA.cpp */
const size_t ClassA::SIZE; // no value here
/* ClassA.h */
class ClassA{
public:
static const size_t SIZE = 10;
int array[SIZE];
funcA();
funcB();
...
};
const size_t ClassA::SIZE;
That should work.
Why not use an enum?, you could define the array as a static variable in a static method (so everything is in the header file)
class ClassA {
public:
enum {SIZE=10;};
static int *array() { static int arr[SIZE]; return arr; }
};

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

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.