Why do I get linker error when I try to compile this in Visual Studio 2008
#include <stdafx.h>
#include <iostream>
#include <map>
#include <string>
class MyClass
{
public:
MyClass () { };
virtual ~MyClass() {};
static std::string niceString (std::map<int, int> mappp) { _myMap = mappp; return "nice string"; };
private:
static std::map<int, int> getMap ( ) { return _myMap; };
static std::map<int, int> _myMap;
};
int main(){
std::map<int, int> mappp;
mappp[1] = 1;
std::cout << MyClass::niceString(mappp);
}
error is:
Error 1 error LNK2001: unresolved external symbol "private: static class std::map<int,int,struct std::less<int>,class std::allocator<struct std::pair<int const ,int> > > MyClass::_myMap" (?_myMap#MyClass##0V?$map#HHU?$less#H#std##V?$allocator#U?$pair#$$CBHH#std###2##std##A) test22.obj test22
You've declared the static member _myMap, but not defined it. Add this line just above int main():
std::map<int, int> MyClass::_myMap;
Think of it like a function that has been declared but not defined in any .cpp file - you get a linker error if you use it.
Related
I've been working with static for quite a long time but now when the header files come I'm a little confused.
The main problem is this code :
#include <iostream>
#include <string>
#include <sstream>
#include <set>
#ifndef WORD_H
#define WORD_H
#include<unordered_map>
class Word
{
private:
std::string word;
int k;
static std::unordered_map<std::string, int> x;
public:
Word(std::string word) : word(word)
{
if (x.find(word) != x.end())
x.insert({ word , 0 });
else
{
x[word]++;
}
}
std::string getWord() const
{
return x.find(this->word)->first;
}
int getCount() const
{
return x.find(this->word)->second;
}
friend bool operator<(const Word& a, const Word& b);
};
bool operator<(const Word& a, const Word& b)
{
return a.getWord() < b.getWord();
}
#endif
std::ostream& operator<<(std::ostream& out, const Word& w) {
return out << w.getWord() << " " << w.getCount();
}
void printWordCounts(const std::string& line) {
std::istringstream lineIn(line);
std::set<Word> words;
std::string wordStr;
while (lineIn >> wordStr) {
words.insert(Word(wordStr));
}
for (Word w : words) {
std::cout << w << std::endl;
}
}
int main() {
std::string line;
std::getline(std::cin, line);
printWordCounts(line);
std::cout << "---" << std::endl;
std::getline(std::cin, line);
printWordCounts(line);
return 0;
}
I know that there is a problem with the static keyword, but what exactly is it?
Also, the error is one of my favourites. Those errors between linker and STL:
Error LNK2001 unresolved external symbol "private: static class std::unordered_map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::hash<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::equal_to<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int> > > Word::x" (?x#Word##0V?$unordered_map#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##HU?$hash#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###2#U?$equal_to#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###2#V?$allocator#U?$pair#$$CBV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##H#std###2##std##A) ConsoleApplication63 C:\Users\Ivo\source\repos\ConsoleApplication63\ConsoleApplication63\ConsoleApplication63.obj 1
I hope that someone can give me an explanation.
You have only declared the static member x. You also need to define it outside the class like this:
std::unordered_map<std::string, int> Word::x;
From c++17, you can define x inside the class definition like this:
inline static std::unordered_map<std::string, int> x;
Static variable declarations in classes are identical to declaring a global variable in a header file, except it's 'symbol' lies within the namespace of the class and therefore access to it is protected with visibility levels. This means that like global variable declarations, static class variable declarations have 'weak' linkage and a compilation unit needs to define the symbol definition, so that the linker can tie the memory associated with the variable declarations in other files to exactly one variable.
Defining the static variable is done outside the class like so:
// <variable type> <class type>::<variable name>;
std::unordered_map<std::string, int> Word::x;
Note that only one .cpp file needs to define the variable
I have myself a very basic program. I am trying to create a static vector in a class, which can then be accessed around my whole program which just creating an instance of that class which has the stored static vector.
here is my test program
testClass.h
#pragma once
#include <vector>
class TestClass
{
public:
TestClass();
~TestClass();
static void AddNumber(int number);
static std::vector<int> Numbers;
};
testClass.cpp
#include "TestClass.h"
TestClass::TestClass()
{
Numbers.push_back(1);
Numbers.push_back(2);
Numbers.push_back(3);
}
TestClass::~TestClass()
{
}
void TestClass::AddNumber(int number)
{
Numbers.push_back(number);
}
main.cpp
#include "TestClass.h"
#include <iostream>
int main()
{
TestClass testClass;
testClass.AddNumber(4);
for (int i = 0; i < testClass.Numbers.size(); i++)
{
std::cout << "Number at " << i << ", is : " << testClass.Numbers.at(i) << std::endl;
}
std::cin.get();
}
When I compile I am getting
Error 2 error LNK2001: unresolved external symbol "public: static class std::vector<int,class std::allocator<int> > TestClass::Numbers" (?Numbers#TestClass##2V?$vector#HV?$allocator#H#std###std##A) c:\Users\mainUser\documents\visual studio 2013\Projects\C++StaticClass\C++StaticClass\main.obj C++StaticClass
Error 3 error LNK2001: unresolved external symbol "public: static class std::vector<int,class std::allocator<int> > TestClass::Numbers" (?Numbers#TestClass##2V?$vector#HV?$allocator#H#std###std##A) c:\Users\mainUser\documents\visual studio 2013\Projects\C++StaticClass\C++StaticClass\TestClass.obj C++StaticClass
Error 4 error LNK1120: 1 unresolved externals c:\users\mainUser\documents\visual studio 2013\Projects\C++StaticClass\Debug\C++StaticClass.exe 1 1 C++StaticClass
Can anyone point me in the right direction on how to fix my problem.
You need to initialize static variable in cpp file. Add following line in testClass.cpp file
std::vector<int> TestClass::Numbers;
In one of my classes, I am trying to use std::priority queue with a specified lambda for comparison:
#pragma once
#include <queue>
#include <vector>
auto compare = [] (const int &a, const int &b) { return a > b; };
class foo
{
public:
foo() { };
~foo() { };
int bar();
private:
std::priority_queue< int, std::vector<int>, decltype(compare)> pq;
};
My program compiles perfectly until I add a .cpp file to accompany the header:
#include "foo.h"
int foo::bar()
{
return 0;
}
This time, my compiler generates an error:
>main.obj : error LNK2005: "class <lambda> compare" (?compare##3V<lambda>##A) already defined in foo.obj
Why can't I create a accompanying .cpp file if my header file contains a lambda?
Compiler: Visual Studio 2012
My main.cpp:
#include "foo.h"
int main(){
return 0;
}
As #Rapptz suggested,
const auto compare = [] (const int &a, const int &b) { return a > b; };
Solved the problem. Why?
Internal vs External linkage. By default, auto, like int has external linkage. So just how:
int j = 5;
In foo.h that would later be included by foo.cpp throws a
Error 2 error LNK2005: "int j" (?j##3HA) already defined in Header.obj
(VS 2013)
However, const makes the linkage internal by default, which means it is only accessible in one translation unit, thereby avoiding the problem.
I'm unable to replicate this problem for some reason. I'm trying this on VS2010 though - not sure if that made a difference. In fact, I tried including your header in two source files and it compiles, links and runs fine.
That said, do you want to consider using std::function. That way you can define the lambda in the cpp code and it won't get defined multiple times for whatever reason. (BTW, where's foo.obj coming from? Do you have another source file that is including this header ?).
foo.h:
#pragma once
#include <queue>
#include <vector>
#include <functional>
typedef std::function<bool (int, int) > comptype;
//auto compare = [] (const int &a, const int &b) { return a > b; };
class foo
{
public:
foo() { };
~foo() { };
int bar();
private:
std::priority_queue< int, std::vector<int>, comptype> pq;
};
Then later in the cpp include and define the lambda and when you create the pq pass it to the constructor.
foo.cpp:
auto compare = [] (const int &a, const int &b) { return a > b; };
foo::foo():pq(compare){}
This way you're deftly not defining the function multiple times.
I'm have some problems with compiling my new project.
Compiler outputs:
1>------ Build started: Project: IRPCore, Configuration: Debug Win32 ------
1> core.cpp
1> Creating library D:\Repo\Inter Role Play Gamemode\sa-mp-0.2-plugin-sdk\IRP\Debug\IRPCore.lib and object D:\Repo\Inter Role Play Gamemode\sa-mp-0.2-plugin-sdk\IRP\Debug\IRPCore.exp
1>core.obj : error LNK2001: unresolved external symbol "public: static class std::tr1::unordered_map<int,struct item,class std::hash<int>,struct std::equal_to<int>,class std::allocator<struct std::pair<int const ,struct item> > > core::itemCache" (?itemCache#core##2V?$unordered_map#HUitem##V?$hash#H#std##U?$equal_to#H#3#V?$allocator#U?$pair#$$CBHUitem###std###3##tr1#std##A)
1>main.obj : error LNK2001: unresolved external symbol "public: static class std::tr1::unordered_map<int,struct item,class std::hash<int>,struct std::equal_to<int>,class std::allocator<struct std::pair<int const ,struct item> > > core::itemCache" (?itemCache#core##2V?$unordered_map#HUitem##V?$hash#H#std##U?$equal_to#H#3#V?$allocator#U?$pair#$$CBHUitem###std###3##tr1#std##A)
1>D:\Repo\Inter Role Play Gamemode\sa-mp-0.2-plugin-sdk\IRP\Debug\IRPCore.dll : fatal error LNK1120: 1 unresolved externals
Here comes core.cpp
#include <iostream>
#include <unordered_map>
#include "core.h"
core::core(void)
{
}
core::~core(void)
{
}
void core::Item_Insert(int uid, item Item)
{
core::itemCache.insert(std::make_pair<int,item>(uid, Item));
return;
}
std::string core::convertNativeStringToString(AMX *amx, cell input)
{
char *string = NULL;
amx_StrParam(amx, input, string);
return string ? string : "";
}
Should I link some more libs or so?
Thanks in advance.
Edit: Here comes core definition from core.h
class core
{
public:
static std::unordered_map<int, item> itemCache;
core(void);
~core(void);
static void Item_Insert(int uid, item Item);
static std::string convertNativeStringToString(AMX *amx, cell input);
private:
};
Add a definition of core::itemCache to core.cpp. In general, static data members of classes are declared in the class definition and defined in a source file.
As #Pete Becker is saying, put this at the top of the cpp:
std::unordered_map<int, item> core::itemCache;
in addition to the
static std::unordered_map<int, item> itemCache;
already in the .h.
Sorry for my bad English. I have 2 projects. Project 1 is a MFC dll that contains class CMyContainer, class CEmployee. Project 2 is my main project. In project 2, I created an instance of CMyContainer of type CEmployee. Now I want to sort the container but I got an error
"error LNK2019: unresolved external symbol "bool __cdecl MyComparer(class CEmployee *,class CEmployee *)" (?MyComparer##YA_NPAVCEmployee##0#Z) referenced in function "public: void __thiscall CMyContainer<class CEmployee>::sortContainer(void)" (?sortContainer#?$CMyContainer#VCEmployee####QAEXXZ)"
How can I fix this problem?
// file MyContainer.h in project 1
#include <vector>
template <class T>
class _declspec(dllexport) CMyContainer
{
public:
CMyContainer(void);
~CMyContainer(void);
...
void sortContainer();
private:
std::vector<T*> items;
typename std::vector<T*>::iterator it;
};
template <class T> void CMyContainer<T>::sortContainer()
{
typedef bool (*comparer_t)(T*,T*);
comparer_t cmp = &MyComparer;
std::sort(items.begin(), items.end(), cmp);
}
//File Employee.h in project 1
#include "MyContainer.h"
class _declspec(dllexport) CEmployee
{
public:
CEmployee(void);
~CEmployee(void);
void setEmployeeCode(CString);
CString getEmployeeCode();
friend bool MyComparer(CEmployee*, CEmployee*);
private:
CString m_szEmployeeCode;
}
//File Employee.cpp in project 1
void CEmployee::setEmployeeCode(CString val){
m_szEmployeeCode= val;
}
CString CEmployee::getEmployeeCode(){
return m_szEmployeeCode;
}
bool MyComparer(CEmployee*pEmp1, CEmployee*pEmp2)
{
return (pEmp1->getEmployeeCode().Compare(pEmp2->getEmployeeCode())<0);
}
//File main.cpp in project 2
#include <..\Models\MyContainer.h>
#include <..\Models\Employee.h>
...
CMyContainer<CEmployee> *pListEmployee;
... // insert into pListEmployee
// sort pListEmployee
pListEmployee.sortContainer();//-> This command cause error
Try to export MyComparer from the .dll with _declspec(dllexport)