Reputation: 44
Possible duplicate: link
Hello everyone,
There's a weird thing that I don't understand about static member variables. If the "definition" (I'm not sure if it is the right word for it) for static variables are in the header file of a class, compiler gives linking errors however if they are in the cpp file, everything is OK.
I have a class like follows (didn't paste the entire thing):
UserInterface.h
class UserInterface
{
public:
UserInterface(void);
~UserInterface(void);
// Some method declarations here
private:
// Some more methods declarations here
// VARIABLES
static bool m_undoRequested;
static ChessViewConstants::MENU_STATE m_displayState;
static ChessModelConstants::PieceMovement m_pieceMovement;
};
// THESE DO NOT WORK (linking errors)
//bool UserInterface::m_undoRequested = false;
//ChessViewConstants::MENU_STATE UserInterface::m_displayState = ChessViewConstants::MAIN_MENU;
//ChessModelConstants::PieceMovement UserInterface::m_pieceMovement(1, 1, 1, 1);
UserInterface.cpp
#include "UserInterface.h"
// These do work.
bool UserInterface::m_undoRequested = false;
ChessViewConstants::MENU_STATE UserInterface::m_displayState = ChessViewConstants::MAIN_MENU;
ChessModelConstants::PieceMovement UserInterface::m_pieceMovement(1, 1, 1, 1);
// Implementation....
ChessConstants.h
namespace ChessModelConstats{
// Some stuff here...
struct PieceMovement {
// A simple Constructor
PieceMovement(int originRow = -1, int originCol = -1,
int targetRow = -1, int targetCol = -1)
: m_originRow(originRow), m_originCol(originCol),
m_targetRow(targetRow), m_targetCol(targetCol)
{
}
// Members
int m_originRow;
int m_originCol;
int m_targetRow;
int m_targetCol;
};
// More stuff here....
}
So why must the static variables be implemented inside the cpp file? Why can't I append at the end of the header file?
A second question: how can I initialize the struct variable (m_pieceMovement) like the follows:
m_pieceMovement.m_originCol = -1;
m_pieceMovement.m_originRow = -1;
m_pieceMovement.m_targetCol = -1;
m_pieceMovement.m_targetRow = -1;
It seems I'm missing a fundamental information here, don't be shy to throw in some novice tips here and there :)
Thanks in advance,
John John
EDIT: Here are the linking errors:
1>MasterController.obj : error LNK2005: "private: static bool UserInterface::m_undoRequested" (?m_undoRequested@UserInterface@@0_NA) already defined in Execution.obj 1>MasterController.obj : error LNK2005: "private: static enum ChessViewConstants::MENU_STATE UserInterface::m_displayState" (?m_displayState@UserInterface@@0W4MENU_STATE@ChessViewConstants@@A) already defined in Execution.obj 1>MasterController.obj : error LNK2005: "private: static struct ChessModelConstants::PieceMovement UserInterface::m_pieceMovement" (?m_pieceMovement@UserInterface@@0UPieceMovement@ChessModelConstants@@A) already defined in Execution.obj 1>UserInterface.obj : error LNK2005: "private: static bool UserInterface::m_undoRequested" (?m_undoRequested@UserInterface@@0_NA) already defined in Execution.obj 1>UserInterface.obj : error LNK2005: "private: static enum ChessViewConstants::MENU_STATE UserInterface::m_displayState" ?m_displayState@UserInterface@@0W4MENU_STATE@ChessViewConstants@@A) already defined in Execution.obj 1>UserInterface.obj : error LNK2005: "private: static struct ChessModelConstants::PieceMovement UserInterface::m_pieceMovement" (?m_pieceMovement@UserInterface@@0UPieceMovement@ChessModelConstants@@A) already defined in Execution.obj 1>D:\C++\CheatersChess\Debug\CheatersChess.exe : fatal error LNK1169: one or more multiply defined symbols found
Upvotes: 1
Views: 1676
Reputation: 69977
The C++ Standard includes a rule called the one-definition rule. Part of it is 3.2/3:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; [...]
When the static member of your question is defined in the header file, its definition will be included in every .obj file that is compiled from a .cpp file that includes that header. Since many files may include that header, you get multiple definitions, which is a violation of that rule. (Note that for this violation it does not matter whether all these definitions are identical.)
Whereas, when you place the definition in a .cpp file, the definition is included only in the .obj file that is compiled from that one .cpp file, causing no duplicate definitions when you link the program.
Regarding the second question: You need to define a constructor that takes the desired values for the members as arguments. You have in fact already done that. You can use that to define the static member (in the .cpp file):
ChessModelConstants::PieceMovement UserInterface::m_pieceMovement(-1,-1,-1,-1);
Upvotes: 1