Linker Error when separating code into .h and .cpp files - c++

I have an implementation for printing out enum values in c++
If I put all the code in a .h file, everything works nicely. If I separate out the function implementation into .cpp files, I get a linker error.
Here is my main file
#include <iostream>
#include <vector>
#include "Day.h"
using namespace std;
int main(){
initializeDayNames();
Day a = Clubs;
cout << a;
}
Here is the .h file
#ifndef __Day__
#define __Day__
#include <iostream>
#include <vector>
#include <string>
using namespace std;
enum Day {Clubs, Hearts, Diamonds, Spades} ;
vector<string> DayNames = vector<string>();
ostream & operator<<(ostream & out, Day cs);
void initializeDayNames();
#endif
and the .cpp file
#include <iostream>
#include "Day.h"
#include<string>
#include<vector>
using namespace std;
void initializeDayNames(){
DayNames.push_back("Clubs");
DayNames.push_back("Hearts");
DayNames.push_back("Diamonds");
DayNames.push_back("Spades");
}
ostream & operator<<(ostream & out, Day cs){
out << DayNames[cs];
return out;
}
What am I doing wrong here
The specific error is
Error 1 error LNK2005: "class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > DayNames" (?DayNames##3V?$vector#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V?$allocator#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###2##std##A) already defined in Day.obj main.obj
and
Error 2 fatal error LNK1169: one or more multiply defined symbols found

You are initializing two copies of
vector<string> DayNames = vector<string>();
because you included the header twice.
You should replace it with
extern vector<string> DayNames;
in the h file and
vector<string> DayNames = vector<string>();
in the cpp file.
Also you seem to have two copies of
ostream & operator<<(ostream & out, Day cs);
The reason your header guards isn't helping this case is that when you include the headers, you basically duplicate the definitions in all your files that you have included the header.
In C, when you declare a variable, you basically instantiate it/allocate static space for it. When you put the variable declaration in the header, what you are effectively doing is allocating static storage space for the variable in two different objects, giving you your error.

You're missing extern on the DayNames declaration.

Related

Static unordered_map pointer initialitation in C++

I got this C++ code:
Client.h:
#include <unordered_map>
using namespace std;
class Client{
static unordered_map<int, Client*>* clients;
public:
static void initializeClients();
}
Client.cpp
#include "Client.h"
#include <unordered_map>
using namespace std;
void Client::initializeClients(){
clients = new unordered_map<int, Client*>();
}
But the linker gives me a LNK2001 unresolved external symbol for the unordered_map. I have no idea of what I am doing wrong, but it seems that I am missing something. I am using Visual Studio 2013.
Any idea? Thank you in advice!
you need to declare clients in your cpp file :
#include "Client.h"
#include <unordered_map>
using namespace std;
unordered_map* Client::clients;
void Client::initializeClients(){
clients = new unordered_map<int, Client*>();
}
explenation:
header file only tells the linker what kinds of symbols some cpp file(s) has. declaring a variable in the header file does not makes this variable appear by it self. here you need to instantiate the static map pointer in the cpp file by declaring it , and make other files know about him by specifing it in the header file
summery :
static member variables and global variables need to be declared also in some cpp file in order to get instantiated

Error LNK2019 while implementing a constructor

I am having some trouble with the implementation of a constructor and I cannot figure out what is the problem. I have spent a lot of time with this problem: it would be grateful some kind of advice.
The main code is:
#include "stdafx.h"
#include "Rocket.h"
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
Rocket* rocket;
rocket=new Rocket();
//LLA* position=rocket->positionLLA;
return 0;
}
Rocket.h
#pragma once
#include "LLA.h"
class Rocket {
public:
Rocket(); // Default constructor
LLA* positionLLA;
};
Rocket.cpp
#include "stdafx.h"
#include "Rocket.h"
#include <iostream>
using namespace std;
Rocket::Rocket() // Default constructor
{
// Initialise the position
positionLLA=new LLA();
}
The error says:
error LNK2019: unresolved external symbol "public: __thiscall Rocket::Rocket(void)" (??0Rocket##QAE#XZ) referenced in function _main.
I know the error has something to do with not having declared a variable, but I think I have declared all classes and constructors.
PS: I am using Visual Studio 2008 in order to add dependencies.
I am assuming LLA is correctly defined in your .h file
Are you compiling Rocket.cpp into Rocket.o and main.cpp into main.o and then linking the two object files together?
Your error seems to imply that the linker cannot obtain symbol information from Rocket.o, which usually means Rocket.o was not found
Oh, as a detail, since Rocket is using an LLA*, you don't need to include LLA.h in Rocket.h, you can simply forward-declare
class LLA;
You might want to add #ifndef, #define, and #endif to your header files. Having multiple includes of the same thing in different files can lead to complications.

Expected ')' before string, STD:: not fixing

In an .h file, I have the following code.
#ifndef COUNTEDLOCATIONS
#define COUNTEDLOCATIONS
#include <iostream>
#include <string>
struct CountedLocations {
CountedLocations();
CountedLocations(std::string url, int counter);
std::string url;
int count;
//below is code for a later portion of the project
bool operator== (const CountedLocations&) const;
bool operator< (const CountedLocations&) const;
};
In my .cpp file that includes the .h file, my code is
#include "countedLocs.h"
#include <iostream>
#include <string>
using namespace std;
CountedLocations(std::string url, int counter)
{
}
I get the error "Expected ')' before 'url'. I've tried commenting out the empty constructor in the .h file, I've tried messing with semicolons, I've tried removing the std:: that prefixes the 'string url', but nothing seems to work. I tried looking at a similar problem on StackOverflow, but all three of the solutions do nothing. How can I fix this?
EDIT: Originally, I had
CountedLocations::CountedLocations(std::string url, int counter)
instead of
CountedLocations(std::string url, int counter)
But that gave me the error "Extra qualification 'CountedLocations::' on member 'CountedLocations' [-fpermissive], so I elected not to use it.
Move need the #include <string> from the .cpp to the .h file so that the file countedLocs.h knows about std::string definition. In your case with one cpp you can switch the order of includes but it would be better to have it in the header there (countedLocs.h) if you plan to use it in other places also.
#include <iostream>
#include <string>
#include "countedLocs.h"
If this is really all of your code then you don't have a definition of std::string (ie #include ) before your struct is defined.
.h files should be able to be compiled all by themselves. put #include in the .h file (and some include guards too!)
In your cpp file (not your header file), you should have this:
CountedLocations::CountedLocations(std::string url, int counter)
{
}
not this:
CountedLocations(std::string url, int counter)
{
}
But that gave me the error "Extra qualification 'CountedLocations::'
on member 'CountedLocations' [-fpermissive], so I elected not to use
it.
That's the error you would get if you put the qualification on the declaration of the constructor in your class body.

Unresolved external symbol error while using vectors defined in a header file

I am new to C++. I had an unresolved external symbol error while using vectors and didn't know what was going wrong so I've replicated it here.
I am using MS Visual Studio 2011. The exact error is:
error LNK2001: unresolved external symbol "class std::vector > abc"
(?abc##3V?$vector#VmyClass##V?$allocator#VmyClass###std###std##A)
I have my class declaration in myClass.h:
#ifndef __MYCLASS__
#define __MYCLASS__
class myClass{
public:
int var;
myClass(void);
myClass (int k);
};
#endif
and my class definition in myClass.cpp:
#include"myClass.h"
myClass::myClass(void){
var=0;
}
myClass::myClass (int k){
var=k;
}
header.h :
ifndef __HEADER__
#define __HEADER__
#include<iostream>
#include<vector>
#include"myClass.h"
using namespace std;
extern std::vector<myClass> abc;
#endif
main.cpp :
#include <iostream>
#include <vector>
#include "myClass.h"
#include "header.h"
using namespace std;
int main(){
abc.push_back(myClass(5));
return 1;
}
This is where I get the unresolved external symbol error. Now I tried putting all of these in a single file and it compiled alright.
THE FOLLOWING FILE IS NOT INCLUDED IN THE ABOVE PROJECT.
#include<iostream>
#include<vector>
#include"myClass.h"
using namespace std;
class myClass{
public:
int var;
myClass(void){
var=0;
}
myClass (int k){
var=k;
}
};
int main(){
std::vector<myClass> abc;
abc.push_back(myClass(5));
return 1;
}
The solution has been given at What is an undefined reference/unresolved external symbol error and how do I fix it?
but I can't figure out how to implement it.
You do not have a definition for this vector:
extern std::vector<myClass> abc;
An extern declaration only tells the compiler that the object exists and it is defined somewhere. But you haven't defined it anywhere.
Add this at global namespace scope in one (and only one!) of your .cpp files:
std::vector<myClass> abc;
Actually, considering that you are not using abc from different translation units (i.e. .cpp files) you do not need the extern declaration at all. Just place your vector in main.cpp, since that is the only place where you are using it.
Also, avoid using directives, especially at namespace scope (since it easily leads to nasty name clashes with entities from the Standard Library):
using namespace std; // THIS IS BAD, DON'T DO IT
Considering that you are qualifying the names of entities from the std namespace already, you don't really need the above.
You declared abc as extern but you never provided definition for it.
Try add definition inside main.cpp:
#include <iostream>
#include <vector>
#include "myClass.h"
#include "header.h"
using namespace std;
std::vector<myClass> abc; //^^add this line
int main(){
abc.push_back(myClass(5));
return 1;
}
However, IMHO using extern here in your code seems useless. Meanwhile, I don't think it is good to name a header file as header.h.
You have abc as a local variable. It should be a global variable. Only then extern would work.
But if you only want to access it as a local variable from within main() and not from another compiled CPP file/object, then it is pointless to use an extern. The extern is only needed if the variable is global and to be accessed from another compiled CPP/object.

error LNK2019: unresolved external symbol (simple code)

this is a pretty simple code that just is coming up with an error even though I have it written the same way other people doing the same code have it
1>assigntment5.obj : error LNK2019: unresolved external symbol "class std::basic_string,class std::allocator > __cdecl promptForString(class std::basic_string,class std::allocator >)" (?promptForString##YA?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V12##Z) referenced in function _main
1>c:\users\aweb\documents\visual studio 2010\Projects\Assignment5\Debug\Assignment5.exe : fatal error LNK1120: 1 unresolved externals
the .cpp file
#include <iostream>
#include <string>
#include "anw65_Library.h"
using namespace std;
string promptForString(string prompt);
int main()
{
string name = promptForString("What is the filename?: ");
system("pause");
return 0;
}
the .h file
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
static string promptFromString(string prompt)
{
string filename;
cout << prompt;
cin >> filename;
return filename;
}
You never define prompt**For**String, you defined prompt**From**String. Spelling matters. Also:
Why are you defining functions in your .h file? Just declare them there and define them in the .cpp file (unless they're templates).
Don't put using namespace <whatever> in a header file. You're just mucking up the global namespace of whatever includes your header.
You don't need to mark that function as static.
This line:
string promptForString(string prompt);
In your .cpp file is causing issues. It's forward delcaring a function with external linkage. However, the function your header is:
static string promptFromString(string prompt)
{
...
The important part here is the static. static means it has internal linkage. Either get rid of the static, or get rid of the forward declaration, because a function can't have both internal and external linkage.
Edit: also, Ed S. made a good find with your typo.
you call promptForString() from your main function while you have promptFromString() defined in .h file.
You might want to change one of the definitions.