I am working on a project for school. I am aware of my circular dependency(And have read most of the resolutions here for that previously) but it works currently the way I need it to. Sadly I'm pretty sure it is also the cause of my woes. I would like to include concol.h so that it can be used with both files (I'd like to add some color to my output - not a requirement for my assignment but something I would like to do). I've tried placement of this header file in several different locations and I always get the same errors. I considered using the forward declaration like I did to work with the circular dependency but I don't think that will work with a namespace.
Errors:
1>Flight.obj : error LNK2005: "void * eku::std_con_out" (?std_con_out#eku##3PAXA) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "bool eku::colorprotect" (?colorprotect#eku##3_NA) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "enum eku::concol eku::textcol" (?textcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "enum eku::concol eku::backcol" (?backcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "enum eku::concol eku::deftextcol" (?deftextcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "enum eku::concol eku::defbackcol" (?defbackcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "void * eku::std_con_out" (?std_con_out#eku##3PAXA) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "bool eku::colorprotect" (?colorprotect#eku##3_NA) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "enum eku::concol eku::textcol" (?textcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "enum eku::concol eku::backcol" (?backcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "enum eku::concol eku::deftextcol" (?deftextcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "enum eku::concol eku::defbackcol" (?defbackcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>D:\School Stuff\Fall 2015\CIST 2362 C++ II\Final - Airline Reservation System\Debug\Final - Airline Reservation System.exe : fatal error LNK1169: one or more multiply defined symbols found
Source.cpp
#include <fstream>
#include <iostream>
#include <iomanip>
#include "FlightComparators.h" //includes Flight.h
#include "LocationComparators.h"
//prototypes
//methods
Flight.h
#ifndef FLIGHT_H
#define FLIGHT_H
#ifndef BOARDINGPASS_H
#include "BoardingPass.h"
#endif
#include <algorithm>
#include <string>
#include <vector>
#include "Location.h"
#include "Validate.h"
#include "AirlineTypeA.h"
#include "AirlineTypeB.h"
class BoardingPass;
class Flight{
private:
Location *departureLoc;
Location *destinationLoc;
char departureTime[6];
char arrivalTime[6];
int number;
int freqFlyerMiles;
int curOccupancy = 0;
Airline *plane;
vector<BoardingPass*> passengers;
public:
//constructor
Flight(Location*, Location*, string, string, int, int, char type);
//getters
Location* getDepartureLoc(){ return departureLoc; }
Location* getDestinationLoc(){ return destinationLoc; }
int getFlightNumber(){ return number; }
int getFreqFlyerMiles(){ return freqFlyerMiles; }
string getDepTime(){ return departureTime; }
string getAriTime(){ return arrivalTime; }
int getCurOccupancy(){ return curOccupancy; }
Airline* getPlane(){ return plane; }
vector<BoardingPass*> getPassengerList(){ return passengers; }
bool getIsFull(){ return this->plane->getMaxPass() > curOccupancy; }
void addPass(string, string, string);
void cancelReservation(int);
void displayPassengers();
void sortPassengers();
};
#endif
BoardingPass.h
#ifndef BOARDINGPASS_H
#define BOARDINGPASS_H
#ifndef FLIGHT_H
#include "Flight.h"
#endif
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class Flight;
class BoardingPass{
private:
string fName;
string lName;
Flight* flight;
string seat;
public:
BoardingPass(string, string, Flight *flt, string seat);
string getFName(){ return fName; }
string getLName(){ return lName; }
string getSeat(){ return seat; }
void displayBoardingPass();
void writeBoardingPass(fstream&);
};
#endif
concol.h
#ifndef INC_EKU_IO_CONCOL
#define INC_EKU_IO_CONCOL
/*Header file to color text and background in windows console applications
Global variables - textcol,backcol,deftextcol,defbackcol,colorprotect*/
#include<windows.h>
#include<iosfwd>
namespace eku
{
#ifndef CONCOL
#define CONCOL
enum concol
{
black = 0,
dark_blue = 1,
dark_green = 2,
dark_aqua, dark_cyan = 3,
dark_red = 4,
dark_purple = 5, dark_pink = 5, dark_magenta = 5,
dark_yellow = 6,
dark_white = 7,
gray = 8,
blue = 9,
green = 10,
aqua = 11, cyan = 11,
red = 12,
purple = 13, pink = 13, magenta = 13,
yellow = 14,
white = 15
};
#endif //CONCOL
HANDLE std_con_out;
//Standard Output Handle
bool colorprotect = false;
//If colorprotect is true, background and text colors will never be the same
concol textcol, backcol, deftextcol, defbackcol;
/*textcol - current text color
backcol - current back color
deftextcol - original text color
defbackcol - original back color*/
inline void update_colors()
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(std_con_out, &csbi);
textcol = concol(csbi.wAttributes & 15);
backcol = concol((csbi.wAttributes & 0xf0) >> 4);
}
inline void setcolor(concol textcolor, concol backcolor)
{
if (colorprotect && textcolor == backcolor)return;
textcol = textcolor; backcol = backcolor;
unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
SetConsoleTextAttribute(std_con_out, wAttributes);
}
inline void settextcolor(concol textcolor)
{
if (colorprotect && textcolor == backcol)return;
textcol = textcolor;
unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
SetConsoleTextAttribute(std_con_out, wAttributes);
}
inline void setbackcolor(concol backcolor)
{
if (colorprotect && textcol == backcolor)return;
backcol = backcolor;
unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
SetConsoleTextAttribute(std_con_out, wAttributes);
}
inline void concolinit()
{
std_con_out = GetStdHandle(STD_OUTPUT_HANDLE);
update_colors();
deftextcol = textcol; defbackcol = backcol;
}
template<class elem, class traits>
inline std::basic_ostream<elem, traits>& operator<<(std::basic_ostream<elem, traits>& os, concol col)
{
os.flush(); settextcolor(col); return os;
}
template<class elem, class traits>
inline std::basic_istream<elem, traits>& operator>>(std::basic_istream<elem, traits>& is, concol col)
{
std::basic_ostream<elem, traits>* p = is.tie();
if (p != NULL)p->flush();
settextcolor(col);
return is;
}
} //end of namespace eku
#endif //INC_EKU_IO_CONCOL
In concol.h you're defining variables inside a namespace, not declaring them. The variables need to be externed
extern HANDLE std_con_out;
in the header (to define them), then declared (without the extern) in a .cpp file (concol.cpp).
The symbols indicated by the linker as "already defined" are items that are declared in header files, but outside of any class. (In "file scope".) As a result, every .cpp file which includes these header files is trying to redefine storage for them. When the linker tries to link the object files together, it sees these multiple definitions, and it complains about them.
The best thing to do to solve your problem is to make all these items "static data members" of a class. This means declaring them within a class, and marking them as static.
If you do not want to move them inside a class, then you must see to it that they will be declared as "extern" when included by all .cpp files but one. This way, only one .cpp file will try to define storage for them, and the linker will be happy.
This is usually done as follows:
a.cpp:
#define DECLARE_STORAGE
#include "myheader.h"
b.cpp, c.cpp etc:
#include "myheader.h" //without defining DECLARE_STORAGE
myheader.h
#ifdef DECLARE_STORAGE
#define POSSIBLY_EXTERN
#else
#define POSSIBLY_EXTERN extern
#endif
POSSIBLY_EXTERN int my_integer;
this will cause a.cpp to compile the statement
int my_integer;
while b.cpp, c.cpp etc. will compile the statement
extern int my_integer;
Related
I have a header file, defining the chunk class:
#pragma once
#include <vector>
#include "Tile.h"
#include "Numerics.h"
namespace boch {
class chunk {
public:
chunk();
static const uint defsize_x = 16;
static const uint defsize_y = 16;
std::vector<std::vector<tile*>> tilespace;
tile* getat(vint coords);
void fillc(tile t);
};
}
Then, I defined the implementation of the class in Chunk.cpp file:
#include "Chunk.h"
boch::chunk::chunk() {
tilespace = std::vector<std::vector<tile*>>(defsize_x);
for (int x = 0; x < defsize_x; x++) {
std::vector<tile*> temp = std::vector<tile*>(defsize_y);
tilespace[x] = temp;
}
}
void boch::chunk::fillc(tile t) {
for (int x = 0; x < defsize_x; x++) {
for (int y = 0; y < defsize_y; y++) {
tilespace[x][y] = new tile(t);
}
}
}
boch::tile* boch::chunk::getat(vint coords) {
return tilespace[coords.x][coords.y];
}
(vint is a typedef of boch::vector<int> which is the custom X,Y vector, if that helps)
Then, I use it in the main function in BochGrounds.cpp file:
#include <iostream>
#include "Layer.h"
#include "Gamegrid.h"
int main()
{
boch::layer newlayer = boch::layer(boch::vuint(16, 16));
boch::chunk newchunk = boch::chunk();
boch::gamegrid newgrid = boch::gamegrid();
newchunk.fillc(boch::tile());
newgrid.addchunk(boch::cv_zero, &newchunk);
newgrid.drawtolayer(&newlayer);
newlayer.draw(std::cout);
}
Tile class defines the gamegrid class, chunk includes tile class, gamegrid includes chunk & entity (which includes tile as well). Layer class includes only tile. All header files have #pragma once directive. When trying to compile, I'm getting the following error:
LNK2019 unresolved external symbol "public: __cdecl boch::chunk::chunk(void)" (??0chunk#boch##QEAA#XZ) referenced in function main
LNK2019 unresolved external symbol "public: void __cdecl boch::chunk::fillc(class boch::tile)" (?fillc#chunk#boch##QEAAXVtile#2##Z) referenced in function main
and as the result:
LNK1120 2 unresolved externals
Other StackOverflow answers suggest that the linker cannot see implementations of both fillc() and chunk constructor functions, but I cannot see why if it is even the problem here. Please help. (Linker settings haven't been changed, and are default for MVSC 2019)
Thanks sugar for the answer. I deleted both header and .cpp files and readded them, and it worked like a charm. I suppose I have added either header or .cpp file just by directly adding a new file to the header/source folder instead of adding it to the project (RMB click on the project > add new item).
I keep getting this Visual C++ 2010 LNK2005 linker error saying I have multiple definitions of two functions that are contained in "Error.h". (a header I made for error display)
My project is like this:
BaseImage.h
BaseImage.cpp --> includes BaseImage.h , Error.h
PNGImage.h --> includes BaseImage.h
PNGImage.cpp --> includes PNGImage.h , Error.h
main.cpp --> includes PNGImage.h
And, of course, Error.h:
/*
Optional macros:
AE_EXIT_AT_ERROR
*/
#pragma once
#include <stdexcept>
void aeError(const char *str, int code=1)
{
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
void aeAssert(bool b, const char *failStr = "assertion failed")
{
if(!b)
aeError(failStr);
}
I have #pragma once in every header file, and I tried adding include guards to Error.h as well.
Here's the compile output:
1>PNGImage.obj : error LNK2005: "void __cdecl aeError(char const *,int)" (?aeError##YAXPBDH#Z) already defined in BaseImage.obj
1>PNGImage.obj : error LNK2005: "void __cdecl aeAssert(bool,char const *)" (?aeAssert##YAX_NPBD#Z) already defined in BaseImage.obj
1>C:\...\Project.exe : fatal error LNK1169: one or more multiply defined symbols found
Could this be a bug?
When you define functions in a .h file, make them inline. Otherwise, the function definitions are part of the object code of all the .cpp files that #include it, with external linkage.
inline void aeError(const char *str, int code=1)
{
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
inline void aeAssert(bool b, const char *failStr = "assertion failed")
{
if(!b)
aeError(failStr);
}
The other option for you is to declare the functions in the .h file and define them in exactly one .cpp file.
The .h file:
extern void aeError(const char *str, int code=1);
extern void aeAssert(bool b, const char *failStr = "assertion failed");
The .cpp file:
// Don't use inline and don't include the default argument values.
void aeError(const char *str, int code)
{
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
void aeAssert(bool b, const char *failStr)
{
if(!b)
aeError(failStr);
}
In such form...
#ifndef UNICODE
#define UNICODE
#endif
#include <Windows.h>
#include <iostream>
class A
{
public:
void makeFoo(TCHAR* output)
{
wcscpy(outputBuffer,TEXT("Hello world ♥"));
}
private:
static const int MAX_OUTPUT_SIZE=2000;
static TCHAR outputBuffer[MAX_OUTPUT_SIZE];
};
int main()
{
TCHAR string[255];
A example;
example.makeFoo(string);
MessageBox(0,string,0,0);
system("Pause");
return 0;
}
... we have a
linking error!
1>main.obj : error LNK2001: unresolved external symbol "private:
static wchar_t * A::outputBuffer" (?outputBuffer#A##0PA_WA)
The linker error occurs because you have not provided a definition for the A::outputBuffer anywhere. Fix this by writing this in file scope:
TCHAR A::outputBuffer[A::MAX_OUTPUT_SIZE];
The value of string is unexpected because that buffer is uninitialized; makeFoo does nothing with its argument, and you do not initialize the buffer manually. Therefore it can contain anything at all ("garbage").
Add:
TCHAR A::outputBuffer[A::MAX_OUTPUT_SIZE];
above main().
I have the following project files:
//connections.cpp
#include "stdafx.h"
#include "LibraryHeaders.h"
#include "FileManager.h"
#define WSAVersion 0x202
#define GSMsgID 0x100
extern HWND Main_hWnd;
bool InitConnections ()
{
FileManager::ConnectFile *connectfile = FileManager::ReadConnectFile(connectfile);
SockBase GSConnection(WSAVersion, TCP, connectfile->GS_IP, connectfile->GS_Port, Main_hWnd, GSMsgID);
if (GSConnection.Connect() != true) {return false;}
return true;
}
//FileManager.cpp
#include "stdafx.h"
#include "FileManager.h"
#include "LibraryHeaders.h"
using namespace FileManager;
ConnectFile* ReadConnectFile(ConnectFile *ConnectStruct)
{
FileLibrary connectfile("DMOConnection.cfg");
if (connectfile.OpenFile(HEAP, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, PAGE_READWRITE) != true) {return false;}
ConnectStruct->GS_IP = connectfile.parser->str_GetToken((char*)connectfile.FileBuff);
if (ConnectStruct->GS_IP == (const char*) -1) {return false;}
ConnectStruct->GS_Port = connectfile.parser->int_GetToken((char*)connectfile.FileBuff);
if (ConnectStruct->GS_Port == -1) {return false;}
return ConnectStruct;
}
//FileManager.h
namespace FileManager
{
struct ConnectFile
{
const char* GS_IP;
unsigned int GS_Port;
};
ConnectFile* ReadConnectFile(ConnectFile*);
}
And when trying to build the project i got this error:
Connections.obj : error LNK2019: unresolved external symbol "struct FileManager::ConnectFile * __cdecl FileManager::ReadConnectFile(struct FileManager::ConnectFile *)" (?ReadConnectFile#FileManager##YAPAUConnectFile#1#PAU21##Z) referenced in function "bool __cdecl InitConnections(void)" (?InitConnections##YA_NXZ)
I dont understand why, the linker should look up and see that ive defined FileManager::ReadConnectFile on FileManager.cpp but it doesnt, any tip how to fix this?
You're defining a free function:
ConnectFile* ReadConnectFile(ConnectFile *ConnectStruct)
not a member:
ConnectFile* FileManager::ReadConnectFile(ConnectFile *ConnectStruct)
Totally different.
Also:
using namespace FileManager;
and
error LNK2019: unresolved external symbol "struct FileManager::ConnectFile [...]
suggests you have a namespace FileManager and a struct FileManager... any reason for using the same name?
i fixed it by declaring the function out of the namespace:
namespace FileManager
{
struct ConnectFile
{
const char* GS_IP;
unsigned int GS_Port;
};
}
using namespace FileManager;
ConnectFile* ReadConnectFile(ConnectFile *ConnectStruct);
The IDE is VC11 Beta, thanks for the answers.
The code
using namespace FileManager;
ConnectFile* ReadConnectFile(ConnectFile *ConnectStruct)
{ ...some definition...}
defines the ReadConnectFile function not in the namespace FileManager, but in global namespace.
I'm having a problem with a vector declaration.
Here's the code:
.h
#ifndef ANIMATEDSPRITE_H_
#define ANIMATEDSPRITE_H_
#include "Sprite.h"
#include <vector>
//using namespace std;
class AnimatedSprite //abstract class to point sprites
{
public:
AnimatedSprite();
~AnimatedSprite();
//gets and sets
Sprite GetMySprite(int _index);
void SetSpriteToList(Sprite _sprite);
int GetState() const;
void SetState(int _state);
//other
private:
std::vector<Sprite> spriteList;
int state; //estado que esse sprite representa (parado esquerda, andando direita, etc)
};
#endif
.cpp
#include "AnimatedSprite.h"
AnimatedSprite::AnimatedSprite()
{
spriteList.clear();
state = NULL;
}
AnimatedSprite::~AnimatedSprite()
{
}
Sprite AnimatedSprite::GetMySprite(int _index)
{
return spriteList[_index];
}
void AnimatedSprite::SetSpriteToList( Sprite _sprite )
{
//Sprite* temp = new Sprite(1,2);
spriteList.push_back(_sprite);
}
int AnimatedSprite::GetState() const
{
return state;
}
void AnimatedSprite::SetState( int _state )
{
state = _state;
}
But I'm getting 2 errors:
Error 1 error LNK2019: unresolved external symbol imp_CrtDbgReportW referenced in function "public: class Sprite & __thiscall std::vector >::operator[](unsigned int)" (??A?$vector#VSprite##V?$allocator#VSprite###std###std##QAEAAVSprite##I#Z) AnimatedSprite.obj
Error 2 fatal error LNK1120: 1 unresolved externals C:\DevProjects\SDLSkeleton\Debug\SDLSkeleton.exe
I've found a solution removing the _DEBUG from the Preprocessor Definitions, but it seems kinda wrong to do that.
Is it the right solution? What's the consequence of removing it?
In the book and documentations I've checked it should be just a common variable declaration, but this errors showed up.
Thanks.
This is because your build is inconsistent: you define _DEBUG macro, but link with release CRT version (/MD). So either remove _DEBUG, or select /MDd option.