Undefined reference to конструктор
The problem I am having is that, when I call a constructor for a class I have created I get the following error.
main.cpp:20: undefined reference to `StaticObject::StaticObject(Graphics*, sf::String,
sf::Vector2)'
This problem can be 'fixed' adding an include for the .cpp file in main.cpp like so.
Although this solves the problem, this seems like a poor solution and goes against what I have been previously told. Is there any other way to solve this problem? I'm using Netbeans 7.3 with g++ to code/compile this program. Below is the relevant code.
main.cpp
main.hpp
StaticObject.hpp
StaticObject.cpp
If I add the following line to main.cpp, the error disappears.
Can anyone please explain:
Why this fixes the problem?
Why the .cpp was not implicitly included through including the .hpp file?
Is there a better way of doing this?
including the cpp file causes the compiler to build that code as part of that file (which you should not do), what you need to do is compile the GameObject/StaticObject.cpp file as its own object, and link the 2 objects together. what are you using to build?
@bizzehdee I just checked the NetBeans project tree, and even though the class was made using NetBeans and there earlier, it seems to have somehow removed itself. After re-adding the relevant files, the problem went away. Thank you so much! Post your answer and I shall mark it as the solution if that's possible as a thank you. :D
6 Answers 6
The undefined reference error indicates that the definition of a function/method (i.e constructor here) was not found by the linker.
And the reason that adding the following line:
fixes the issue, is it brings in the implementation as part of the main.cpp whereas your actual implementation is in StaticObject.cpp . This is an incorrect way to fix this problem.
I haven't used Netbeans much, but there should be an option to add all the .cpp files into a single project, so that Netbeans takes care of linking all the .o files into a single executable.
If StaticObject.cpp is built into a library of its own (I highly doubt that is the case here), then you might have to specify the path to the location of this library, so that the linker can find the implementation.
This is what ideally happens when you build your program:
Although there are ways in gcc/g++ to skip all the intermediate .o file generations and directly generate the main_program , if you specify all the source files (and any libraries) in the same command line.
I just created a new class. In my other class I want to have list where I can store Filter objects.
Filter.h
Filter.cpp
Cars.h
Cars.cpp
so in a function here I try to do this:
which generate this error:
What's the reason for this?
This will not even compile. Are you sure, this is the real code? If so, you're compiling the project in a wrong way. How you do this?
If you're serious about C++, please pick up a good book and learn it properly. The way you're going, you'll end up with a horrible, leaking, buggy java-like mess. C++ is not the same as Java.
Please, please get a good book on C++ and forget everything you know from Java. C++ values completely different things, and you'll only hurt your C++ experience if you try to program the same way as you did in Java.
@Ole-M: Your specific problem is because of the way you are building your code. If you were building it the right way you would not be getting the errors above. The actual problem seems to be that you are not including Filter.cpp in your build. Unlike Java every C++ compiler is different. You need to learn how to use the compiler you have.
1 Answer 1
The error is generated by the linker because it can not see where the definition of the constructor is located.
If you are using an IDE, you should add both .cpp files to the project so that they can be compiled together and the definition would be found by the linker. It not, then you have to combine them yourself -assuming you are using gcc:
will combine them into one executable and should not show you that error
Not the answer you're looking for? Browse other questions tagged c++ g++ or ask your own question.
Linked
Related
Hot Network Questions
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2022.6.22.42430
I have no idea why this is happenning, since I think I have everything properly declared and defined.
I have the following program, designed with templates. It's a simple implementation of a queue, with the member functions "add", "substract" and "print".
I have defined the node for the queue in the fine "nodo_colaypila.h":
Then the implementation in "nodo_colaypila.cpp"
Afterwards, the definition and declaration of the queue template class and its functions:
Then, I have a program to test these functions as follows:
But when I build, the compiler throws errors in every instance of the template class:
undefined reference to `cola(float)::cola()'. (it's actually cola''::cola(), but this doesn't let me use it like that.)
And so on. Altogether, 17 warnings, counting the ones for the member functions being called in the program.
Why is this? Those functions and constructors WERE defined. I thought that the compiler could replace the "T" in the template with "float", "string" or whatever; that was the advantage of using templates.
I read somewhere here that I should put the declaration of each function in the header file for some reason. Is that right? And if so, why?
and maybe nodo_colaypila
And there's a third minor typo: If the parameter to a function has a default value, then this should be defined in the header file, not in the implementation. (More precisely, the (first) declaration should have the default.)
@LightnessRacesinOrbit, answered often yes. Not always fully correctly though :-) There are ways to keep the implementation of a template's member functions in one translation unit, while allowing other translation units to link to them. See my answer.
@LightnessRacesinOrbit: Answered a million times, perhaps! but you didn't even provide a single link and marked this as duplicate.
3 Answers 3
This is a common question in C++ programming. There are two valid answers to this. There are advantages and disadvantages to both answers and your choice will depend on context. The common answer is to put all the implementation in the header file, but there's another approach will will be suitable in some cases. The choice is yours.
The code in a template is merely a 'pattern' known to the compiler. The compiler won't compile the constructors cola::cola(. ) and cola::cola(. ) until it is forced to do so. And we must ensure that this compilation happens for the constructors at least once in the entire compilation process, or we will get the 'undefined reference' error. (This applies to the other methods of cola also.)
Understanding the problem
The problem is caused by the fact that main.cpp and cola.cpp will be compiled separately first. In main.cpp , the compiler will implicitly instantiate the template classes cola and cola because those particular instantiations are used in main.cpp . The bad news is that the implementations of those member functions are not in main.cpp , nor in any header file included in main.cpp , and therefore the compiler can't include complete versions of those functions in main.o . When compiling cola.cpp , the compiler won't compile those instantiations either, because there are no implicit or explicit instantiations of cola or cola . Remember, when compiling cola.cpp , the compiler has no clue which instantiations will be needed; and we can't expect it to compile for every type in order to ensure this problem never happens! ( cola , cola , cola , cola < cola> . and so on . )
- Tell the compiler, at the end of cola.cpp , which particular template classes will be required, forcing it to compile cola and cola .
- Put the implementation of the member functions in a header file that will be included every time any other 'translation unit' (such as main.cpp ) uses the template class.
Answer 1: Explicitly instantiate the template, and its member definitions
At the end of cola.cpp , you should add lines explicitly instantiating all the relevant templates, such as
and you add the following two lines at the end of nodo_colaypila.cpp :
This will ensure that, when the compiler is compiling cola.cpp that it will explicitly compile all the code for the cola and cola classes. Similarly, nodo_colaypila.cpp contains the implementations of the nodo_colaypila <. >classes.
In this approach, you should ensure that all the of the implementation is placed into one .cpp file (i.e. one translation unit) and that the explicit instantation is placed after the definition of all the functions (i.e. at the end of the file).
Answer 2: Copy the code into the relevant header file
The common answer is to move all the code from the implementation files cola.cpp and nodo_colaypila.cpp into cola.h and nodo_colaypila.h . In the long run, this is more flexible as it means you can use extra instantiations (e.g. cola ) without any more work. But it could mean the same functions are compiled many times, once in each translation unit. This is not a big problem, as the linker will correctly ignore the duplicate implementations. But it might slow down the compilation a little.
Summary
The default answer, used by the STL for example and in most of the code that any of us will write, is to put all the implementations in the header files. But in a more private project, you will have more knowledge and control of which particular template classes will be instantiated. In fact, this 'bug' might be seen as a feature, as it stops users of your code from accidentally using instantiations you have not tested for or planned for ("I know this works for cola and cola , if you want to use something else, tell me first and will can verify it works before enabling it.").
The line where this error reported is inside the library it self.
but when I compile the library, it compile OK.
This is the line where error occurred
This is my class .h file
This is .cpp file
Any help will be very appreciate !
@Dong Are you linking against that library?
You get such errors if you forget to link against a library containing the reference.
@jsulm
It already linked
Here is the Compile Output:
Looks like you did not export PropertyToCsvSetting from your library
@VRonin
I don't know what you mean.
The problem is: It compile OK on QT creator 5.7
It compile OK on QT creator 5.7
Ok, sorry, I missed that part. Did you build the library with Qt 5.4.2?
@VRonin
Yes !
all project are in the same SubDir Project
So, I guess the library is static. could you post the 3 .pro files please?
Reran qmake and did a full rebuild?
Dear All: here is my situation
- The class which cause compile Error is PropertyColumnMapping in DynamicObjectCore.pro
- Then CommonBusiness.pro using this class
- And Presentation linked to both CommonBusiness.pro & DynamicObjectCore.pro
Clean + QMake + Rebuild doesn't work.
Here is my Project Structure.
Application.pro
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS +=
Framework
Services
Business
Presentation
Updater
QT += qml quick widgets network sql xml
SUBDIRS +=
CommonBusiness
ServiceBusiness
//Link to Framework.System
CommonBusiness.pro
QT -= gui
QT += qml quick sql xml xmlpatterns network
TARGET = CommonBusiness
TEMPLATE = lib
CONFIG += staticlib c++11
HEADERS +=
MetadataModel/propertycolumnmapping.h
.
unix target.path = /usr/lib
INSTALLS += target
>
QT += qml quick widgets network sql xml xmlpatterns
qtHaveModule(webkitwidgets) QT += webkitwidgets
>
CONFIG(release, debug|release) CONFIG += release force_debug_info
>
RESOURCES += qml.qrc
shared.qrc
Hi I'm afraid that the following code is giving me a "undefined reference to 'strSet::strSet(std::basic_string
The following is a header file for an object strSet which stores a vector of strings.
This is the implementation of my constructors:
And finally in my main function I call the constructor as :
Although I've clearly defined both constructors in the header file and respective cpp file, it tells me that the constructor is undefined. Is there any particular reason why?
Have you tried tempSet = new strSet(string( "hello" )); ? Also, change the constructor to taking a const reference.
Thanks for the reply, unfortunately I have no control over changing the constructor parameters since I am not allowed to change the header file.
However changing it to tempSet = new strSet(string( "hello" )); does not fix the problem.
To be more precise this is not the only error I am getting since I also get a similar "undefined reference" error in my struct definitions:
LOL thank you very much.
I changed with and it worked fine. My apologies I just don't entirely understand the linking step from the compiler.
When I said doesn't it just refer to the header functions, and subsequently find a .cpp file where they are defined?
The reason why I wrote this is because I know it is customary to write to use strcmp function. So when is it useful to include headerfiles as aposed to .cpp files?
No, don't do that. Linking is done by passing parameters to the compiler, not by inclusion. You do NOT include cpp files. (well, you can, but that defeats their entire point).
Please tell me what compiler you are using.
I'm using a g++ compiler.
The code for strset.cpp and strset (at least for the constructors) should be written in the first post.
Oh I feel as though I might have left out something crucial: I infact over wrote the assignment operator function in strSet:
I don't know how badly this might affect my problem however.
I had this exact same problem. The solution was that I forgot to set a target for my CPP file when linking it to the project. What compiler are you using?
in g++, you would normally do it like that:
Basically, this is done to be able to spread your code on multiple files so you don't have to recompile the entire program again after changing just one line. For example, if you have file1.cpp and file2.cpp, you would compile them to get file1.o and file2.o. Linking them gives you the executable. Now if you change file1.cpp you only need to recompile file1.cpp, and link the new file1.o to the old file2.o to create the new executable. Header files are there to provide the interface to an object file, basically so the compiler knows what symbols he can use.
Thank you very much for the explanation. It works now hanst99, using the last compile command you wrote.
Читайте также: