I am new to C++. I have a linker problem between 2 files F1 and F2. In order to be more readable, I rewrote the code and output.
F1.h:
class MYCLASS...
public:....// [constructor] etc
void myMethod(const string& r);
static string s;
F1.cpp:
void myMethod(const string& r)
{
MYCLASS::s=r;
}
[...]
void serialize(...)
{
operation(s,...)
}
F2.cpp:
const string& a;
MYCLASS Obj;
Obj.myMethod(a);
The goal is to use the string a from F2.cpp inside the serialize method from F1.cpp, without adding any argument to the serialize function. For that, I am trying to use the intermediate r variable.
The compilation (compiler based on gcc) gives the errors:
In function `the_function_from_F2.cpp(...)':
F2.cpp:227: undefined reference to `MYCLASS::myMethod(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
: In function `myMethod(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
F1.cpp:197: undefined reference to `MYCLASS::s'
: In function `MYCLASS::serialize(....) const':
F2.cpp:69: undefined reference to `MYCLASS::s'
Thank you for any suggestion !
Change to:
void MYCLASS::myMethod(const string& r)
{
MYCLASS::s=r;
}
std::string MYCLASS::s;
This is still a class method, so you need to specify that.
You forgot to actually define the MYCLASS::s member. It has to be done in a source file like
std::string MYCLASS::s;
What you are doing in the class is only declaring the static variable.
Related
This question already has an answer here:
Linking error using Arduino library with c++'s stringstream
(1 answer)
Closed 4 years ago.
I'm using an ESP8266 with the Arduino IDE to work on a microcontroller project. However I also want to use it as an opportunity to learn more about C++. I'm trying to deserialize a string like "key1:value1;key2:value2;..." into a map of strings, and I came across this question which seemed relevant: Parsing a comma-delimited std::string
So I put it into a function like
void SimpleKeyPairs::deserializeKeyPairs(std::string input, std::map<std::string, std::string>* output)
{
std::stringstream ss(input);
std::string key;
std::string value;
while(ss.good()) {
std::getline(ss, key, ':');
std::getline(ss, value, ';');
output->insert(std::make_pair(key, value));
}
}
However I'm getting compiler errors (copied from IDE) and unfortunately I can't figure out what I need to fix. I did isolate the problem to the line std::stringstream ss(input); but I'm not sure what the issue is.
Arduino: 1.6.13 (Mac OS X), Board: "Adafruit HUZZAH ESP8266, 80 MHz, 4M (3M SPIFFS), v2 Prebuilt (MSS=536), Disabled, None, 921600"
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(locale-inst.o):(.literal._ZSt9use_facetISt5ctypeIcEERKT_RKSt6locale[std::ctype<char> const& std::use_facet<std::ctype<char> >(std::locale const&)]+0x4): undefined reference to `std::__throw_bad_cast()'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(locale-inst.o): In function `std::ctype<char> const& std::use_facet<std::ctype<char> >(std::locale const&)':
/Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/bits/locale_classes.tcc:114: undefined reference to `std::__throw_bad_cast()'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(locale-inst.o): In function `std::numpunct<char> const& std::use_facet<std::numpunct<char> >(std::locale const&)':
/Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/bits/locale_classes.tcc:114: undefined reference to `std::__throw_bad_cast()'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(locale-inst.o): In function `std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > > const& std::use_facet<std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > > >(std::locale const&)':
/Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/bits/locale_classes.tcc:114: undefined reference to `std::__throw_bad_cast()'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(locale-inst.o): In function `std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > > const& std::use_facet<std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > > >(std::locale const&)':
/Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/bits/locale_classes.tcc:114: undefined reference to `std::__throw_bad_cast()'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(locale-inst.o):/Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/bits/locale_classes.tcc:114: more undefined references to `std::__throw_bad_cast()' follow
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(c++locale.o):(.literal._ZNSt6locale5facet18_S_create_c_localeERPiPKcS1_+0x4): undefined reference to `std::__throw_runtime_error(char const*)'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(c++locale.o): In function `std::locale::facet::_S_create_c_locale(int*&, char const*, int*)':
/Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/src/c++98/c++locale.cc:207: undefined reference to `std::__throw_runtime_error(char const*)'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(ios-inst.o):(.literal._ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate[std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate)]+0x4): undefined reference to `std::__throw_ios_failure(char const*)'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(ios-inst.o): In function `std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate)':
/Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/bits/basic_ios.tcc:122: undefined reference to `std::__throw_ios_failure(char const*)'
/Users/jake/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/tools/sdk/lib/libstdc++.a(istream-inst.o): In function `__check_facet<std::ctype<char> >':
/Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/istream:95: undefined reference to `std::__throw_bad_cast()'
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board Adafruit HUZZAH ESP8266.
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
Thanks in advance!
Thanks to Zebrafish for pointing me to this question about sstream with Arduino. Apparently it is difficult to include a lot of std c++ in Arduino projects, including stringstream.
This led me to find this answer, which recommends staying away from Arduino String. I used it to revise my function to this:
#include <string>
#include <cstring>
#include <map>
void SimpleKeyPairs::deserializeKeyPairs(std::string input, std::map<std::string, std::string>* output)
{
char* inputChars = const_cast<char*>(input.c_str());
char* key;
char* value;
key = strtok(inputChars, ":");
value = strtok(NULL, ";");
while(key != NULL && value != NULL) {
output->insert(std::make_pair(key, value));
key = strtok(NULL, ":");
value = strtok(NULL, ";");
}
}
I have a function which has signature :
int alarmCreate(const std::string& familyCode, std::vector<std::pair<std::string,boost::any> >& alarmparameters, const std::string& description);
As can be seen , it has three parameters; string,vector,string.
But when I am building my project I am getting a error :
/root/projects/test/test.cpp:152: undefined reference to
redisHandler::alarmCreate(std::string const&, std::vector<std::pair<std::string, boost::any>, std::allocator<std::pair<std::string, boost::any> > >&, std::string const&)
I see a fourth parameter with type std::allocator , I can't understand where it is coming from.
Do you guys have any idea , why there is a 4th parameter in my function ?
EDIT :: It turns out there is 3 parameters. But I am still curious why I am getting the error. This function is in a static library. When I search this library with "nm" I see my func exists(can be seen below) . Do you have any idea what may I missing?
[root# ~/projects/test/test]# nm ../../lib/libredis.a |grep alarmCreate
000000000000073c T_ZN12redisHandler11alarmCreateERKSsRSt6vectorISt4pairISsN5boost3anyEESaIS6_EES1_
It is a template parameter of the vector. Every standard container have an allocator, and it has a default value so you don't need to bother about this one.
Your method may have been declared but it is not defined.
i got this error and i am not able to solve by myself
source.cpp:85:8: error: request for member ‘put_tag’ in ‘aux’, which is of non-class type ‘Keyword()’
source.cpp:86:8: error: request for member ‘put_site’ in ‘aux’, which is of non-class type ‘Keyword()’
make: *** [source.o] Error 1
the code which gives me this error is
Keyword aux();
aux.put_tag(word);
aux.put_site(site);
I must mention that word and site are char * type
Now, my Keyword class definition is this one:
class Keyword{
private:
std::string tag;
Stack<std::string> weblist;
public:
Keyword();
~Keyword();
void put_tag(std::string word)
{
tag = word;
}
void put_site(std::string site)
{
weblist.push(site);
}
};
Thank you very much!
Update
By modifying
Keyword aux();
aux.put_tag(word);
aux.put_site(site);
in
Keyword aux;
aux.put_tag(word);
aux.put_site(site);
i got this error:
source.o: In function `Algorithm::indexSite(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
source.cpp:(.text+0x2c6): undefined reference to `Keyword::Keyword()'
source.cpp:(.text+0x369): undefined reference to `Keyword::~Keyword()'
source.cpp:(.text+0x4a8): undefined reference to `Keyword::~Keyword()'
source.o: In function `Keyword::put_site(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
source.cpp:(.text._ZN7Keyword8put_siteESs[Keyword::put_site(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)]+0x2a): undefined reference to `Stack<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::push(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status
make: *** [tema3] Error 1
This line does not do what you think:
Keyword aux();
Is declaring a function called aux that takes no arguments and returns a Keyword. You most likely meant to write (without the parentheses):
Keyword aux;
Which declares an object of type Keyword.
UPDATE:
Concerning the next error you are getting, this is because you have a declaration of the constructor and destructor of your class, but not a definition. In fact, the error you are getting comes from the linker, and not from the compiler.
To provide a trivial definition of your constructor and destructor, change this:
Keyword();
~Keyword();
Into this:
Keyword() { }
~Keyword() { }
Or, as long as these member functions do nothing, just omit them at all - the compiler will generate them for you (unless you add some other user-declared constructor, for what concerns the constructor).
Not this
Keyword aux();
aux.put_tag(word);
aux.put_site(site);
but this
Keyword aux;
aux.put_tag(word);
aux.put_site(site);
In your version Keyword aux(); is a function prototype not a variable declaration.
I had the same problem when I type the following code into my main function, I have a List.h and List.cpp files contains my List class.
List<int,int> myList();
bool x=myList.isEmpty();
I get an error of "request for member 'isEmpty' in 'myList', which is of non-class type 'List()'"
the error is because the compiler consider myList() as a function prototype
when I correct the code to be
List<int,int> myList;
bool x=myList.isEmpty();
I got the error "undefined reference to `List::List()" and a couple of similar errors for the destructor.
Further inspection of my code and answers in this page I found that I have to include my List.cpp file in the main.cpp however I included List.h in my List.cpp file but it seems that this information has to be told to the main file as well.
further reading for this tutorial explain why ,if I compile the project without including List.cpp it will compile fine because the List.h file has the prototype but it would fail in the linker stage because the linker would be unable to resolve the call to List() to a specific function.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 8 years ago.
I have this bit of code from a stackoverflow question:
template <typename K, typename V>
bool exists_in(std::map<K,V> const& haystack, K const& needle)
{
return haystack.find(needle) != haystack.end();
}
Being a new user of templates, I still understand what is going on here. Only, I can't seem to apply it.
I have defined
class Varinfo; // meta information about vars
std::map<std::string,VarInfo*> g_varMap; // a map between var names and meta-info
In my main c++ code I have this statement:
// various other uses of g_varMap that don't cause errors then
if ( exists_in( g_VarMap, "fred" ) )
that generates this error.
undefined reference to `bool exists_in<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >,
VarInfo*>(std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char> >, VarInfo*, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >,
std::allocator<std::pair<std::basic_string<char, std::char_traits<char>,
std::allocator<char> > const, VarInfo*> > > const&, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)'
which I completely do not understand.
Can someone tell me why this is complaining? What bitof template knowledge am I missing? I have tried various casting operations on the variable returned by and sent to exists_in() including a std::string( "fred" ). Nothing helped. Some just generated even more meaningless errors.
Undefined reference means it cannot find the definition in any object file. This is a linker error. You need to define the template method within the header file and not in a separate cpp file.
Your code looks okay, I made a rough approximation, you can see it here: http://codepad.org/UvgeTIoC
If your function were available before the point of call you would have no problem. bear in mind that it is template code, so the full implementation has to be included either directly or indirectly:
#include <map>
#include <iostream>
template <typename K, typename V>
bool exists_in(std::map<K,V> const& haystack, K const& needle)
{
return haystack.find(needle) != haystack.end();
}
int main()
{
std::map<int, int> m{{1,1},{2,2}};
std::cout << std::boolalpha;
std::cout << exists_in(m,2) << "\n";
}
output true.
i have an list with some datas list<string> l; and if i pass the value to an class process it gives me error
Process p; p.getnames(l);
and i have an header file process.h with
class Process {
public:
void getnames(list<string> ll);
};
and i have an cpp file process.cpp
void getnames(list<string> ll)
{
// i can use the names here
}
error
undefined reference to `Process::getname(std::list<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >)'
The error you're getting is a linker error because you've defined a free function named getname rather than a member function getname. To fix this, change your .cpp file to have
Process::getname(list<string> names)
And you should be good. The error now is that the compiler thinks you're defining some random function with no connection to Process, so when it compiles the code and someone tries to use Process::getname the linker can't find an implementation for it, and it's not smart enough to know that the free function you defined was intended to be a member function, hence the poor diagnostic.
void Process::getnames(list<string> ll)
{
// i can use the names here
}
When separating definition from declaration, in definition you need to include class name as following:
void Process::getnames(list<string> ll)
{
// i can use the names here
}
What you did is that you defined getnames(list ll) function that returns void.