Background
I have a project named PersonLibrary which has two files.
Person.h
Person.cpp
This library produces a static library file. Another project is TestProject which uses the PersonLibrary (Added though project dependencies in VS008). Everything worked fine until I added a non-member function to Person.h. Person.h looks like
class Person
{
public:
void SetName(const std::string name);
private:
std::string personName_;
};
void SetPersonName(Person& person,const std::string name)
{
person.SetName(name);
}
Person.cpp defines SetName function. When I try to use SetPersonName from TestProject, I get error LNK2005: already defined. Here is how I used it
#include "../PersonLibrary/Person.h"
int main(int argc, char* argv[])
{
Person person;
SetPersonName(person, "Bill");
return 0;
}
Workarounds tried
1 - I have removed the Person.cpp and defined the whole class in Person.h. Error gone and everything worked.
2 - Changed the SetPersonName modifier to static. Like the below
static void SetPersonName(Person& person,const std::string name)
{
person.SetName(name);
}
Questions
Why the code shown first is not working as I expected?
What difference static made here?
What is the approapriate solution for this problem?
Thanks
You either have to
move SetPersonName's definition to a .cpp file, compile and link to the resulting target
make SetPersonName inline
This is a well known case of One Definition Rule violation.
The static keyword makes the function's linkage internal i.e. only available to the translation unit it is included in. This however is hiding the real problem. I'd suggest move the definition of the function to its own implementation file but keep the declaration in the header.
When you compile you're library, its lib file contains a definition for SetPersonName. When you compile your program that uses the library, since it includes the header, and you've written the code inline in the header it also compiles in a definition for SetPersonName. Two definitions for the same function aren't (generally) allowed. The static keyword tells the compiler that the function shouldn't be exposed outside of the current translation unit (discrete piece of code you are compiling), so the definition in the library isn't visible to the linker.
The appropriate solution to this problem depends on your goals. Header files with static function declarations is almost never what you want. From a design standpoint I would recommend getting rid of SetPersonName altogether, and just use Person::SetName.
However, failing that, I would implement it much like you've done for the rest of your functionality, declarations in the header, and implementation in the .cpp. Inline functions associated with a library will tend to diminish many of the advantages of using a library in the first place.
By declaring the function static you are scoping it to the current translation unit, so in effect you have added a new SetPersonName function in your main file, and would be calling that not the one defined in the library.
The correct solution is to declare SetPersonName as extern in person.h and implement it in person.cpp
Person.h
extern void SetPersonName(Person& person,const std::string name);
Person.cpp
void SetPersonName(Person& person,const std::string name)
{
person.SetName(name);
}
The function SetPersonName will be compiled into each objectfile that includes the Person.h file, thus making the linker seeing several functions and giving the error.
By writing static you state that the function will only be visible within a single objectfile. You will still get several functions in you binary but now you will not get the errors.
Try to write inline before the function like
inline void SetPersonName(Person& person,const std::string name)
{
person.SetName(name);
}
...because the function is pretty simple it is OK I think to have it as an inline. An inline will place the necessary code where the function is used, without actually creating a function to be called.
A solution would be to make that function a static method. That will stop the "already defined" errors.
I had a similar situation as described clearly by #logan-capaldo above.
A CPP source file (myfile.cpp) contained a function MyFunction. When building, this got compiled into myfile.obj. But the main CPP file (main.cpp) also included myfile.cpp, so the function MyFunction was being included/compiled/linked twice, leading to the "LNK2005 already defined" error.
This is messy but I didn't have time to fix it properly. The quickest fix (in VS Express 2012) was to right-click myfile.cpp in Solution Explorer, go to Properties and change Excluded From Build to Yes. I guess this prevents one of the OBJ files from being created and/or linked and so removes the error.
For anyone landing here dealing with this error in a Qt project, make sure you don't have any non-signal functions defined under signals: in your header files.
Incorrect, throws LNK2005 on Foo::promiseData():
class Foo : public QObject {
Q_OBJECT
public:
explicit Foo(QObject* parent = nullptr);
signals:
void dataReady(QList<QObject*> data) const;
void promiseData() const; // <-- This function is not supposed to be a signal.
Correct:
class Foo : public QObject {
Q_OBJECT
public:
explicit Foo(QObject* parent = nullptr);
void promiseData() const;
signals:
void dataReady(QList<QObject*> data) const;
Related
Okay so I recently learned how the compiler exactly works and what the "linker" is. From the tutorial videos I've watched I clearly saw that if I include more than once a declaration, to say:
void Log(const char* message);
I would get an error since I am declaring it more than once. But currently, as I am testing it, I've created a header file which contains that particular declaration and I've included it a couple of times in my Main compilation unit, as so:
#include "Log.h"
#include "Log.h"
I have removed the #pragma once statement, nor do I have header guards written, but my program still runs perfectly and without any problems. Since the videos are 2-3 years old, I thought maybe there has been an update, which alltogether removes the need of guards and pragmas, but I do not know for sure.
The tutorials you've seen are correct. You cannot have more than one definition of something unless you use special techniques.
In this case though you don't have a definition.
void Log(const char* message);
is a declaration and you are allowed to have multiples of those. If you change the code to
void Log(const char* message) {}
then you would have a function definition and will get an error.
I would get an error since I am declaring it more than once.
Re-declaration is generally allowed, as long as you don't mix different kinds of declarations with the same name. Following is perfectly legal C++, and always has been:
void Log(const char* message);
void Log(const char* message);
You may have been confused with the one definition rule, which disallows defining things more than once.
I have removed the #pragma once statement, nor do I have header guards written, but my program still runs perfectly and without any problems.
If your header doesn't define anything, then it doesn't need a header guard. It's however simpler to just conventionally always keep the guard so that there is no need to keep track of whether there are definitions or not.
Bonus answer: All definitions are also declarations. It is usually easy to distinguish definitions of classes and functions from forward declarations:
return_type function_name(argument_list); // not a definition of function
return_type function_name(argument_list) { ... } // is a definition of function
class class_name; // not a definition of class
class class_name { // is a definition of class
void member_function(); // not a definition of function
void inline_member_function() { ... }; // is a definition of function
};
void class_name::member_function() { ... } // is a definition of function
Distinguishing variable definitions is a bit harder. Always check the rules when unsure.
this a function forward declaration and you just let the compiler know that a function X will be defined later. in some resources you will find out it's written/said that multiple declaration isn't allowed, but i think cuz of the clean code approach, not a compiler issue. and your case, you just include the declaration twice, the same if you declared the function in two different header files and included both of them in a source file.
Cherno's tutorials?
I think its made crystal clear in the videos that you can't have multiple definitions of a function. The custom header files that you've created are basically chunks of code copy-pasted hence if they include different definitions of the same function or say class it will result in ambiguity and throw an error as expected.
Edit: The point that he wanted to make -
If you write those two same function definitions together in a file then obviously it will throw up an error due to ambiguity arising as I mentioned above, which is detected by the compiler, since its only in a single file.
But when you place those two same definitions in a different file, say your custom created header "log.h" then when you import them into your cpp file twice (or say you import them in another cpp file and build the solution like in visual studio) it will throw up a linker error as the linker is involved (multiple files - wherein the job of the linker is to link them into a combined executable) and it cannot select multiple definitions present in different files. Hence for this case you will get the multiple definitions/signature error. (And including pragmas suppress warnings)
A Solution to resolve that is making the functions static, so that they are defined internally or only for the file they are being compiled against. This makes it possible to have multiple function definitions of the same function in different files with no linking error. Another option is to make it in-line. These cases provide you with multiple definitions with no errors, otherwise it will throw up errors.
I came across an exercise that I found online.
This exercise consist of "virtual void" that I never seen before of how it works.
So the exercise contain 1 header file named plans.h
namespace plans {
class HumanActions {
public:
virtual void goTo() { }
virtual void haveANiceColdBeer() { }
};
void applyPlan(HumanActions &actions);
}
and one cpp file
#include "Plans.h"
using plans::HumanActions;
using plans::applyPlan;
void
plans::applyPlan(HumanActions &actions) {
actions.goTo();
actions.haveANiceColdBeer();
}
I tried to run the function by having another main file that runs like
#include "Plans.h"
using plans::HumanActions;
using plans::applyPlan;
int main() {
HumanActions actions;
applyPlan(actions);
}
Unfortunately it does not run and it says that I have undefined reference to `plans::applyPlan(plans::Actions&)' so My question is how do you pass the functions for those argument given?
You have declared "void applyPlan(HumanActions &actions)" in the header file, but you have not defined (implemented) it anywhere, which is why you have the undefined symbol.
If in main(), you called applyZombiePlan() instead of applyPlan() you should be OK.
"Undefined reference" is a linker error that means the implementation for a function couldn't be found. In other words, it typically means you declared the function, and called the function, but forgot to actually write the function.
Your error message refers to plans::applyPlan(plans::Actions&), but the closest declaration I see is void applyPlan(HumanActions &actions);, which has a different argument type. Assuming this isn't just a mix-up between different versions of the code in your post, you might have accidentally declared two different applyPlan functions but only implemented one of them.
If your program consists of more than one .cpp file, another possible reason is that you're accidentally trying to compile and link a single file as if it were a complete program instead of linking all the modules together. That'd make the linker not see anything defined in the other .cpp files. If you're a beginner, your best bet is to compile all your source files at once with a single command line, e.g. g++ *.cpp -o myprog.
Calling a virtual function is no different from calling a regular function, BTW, and applyPlan is not a virtual function anyway.
I think you can make use of extern keyword. whenever you are actually defining your global function, you can say void XYZ(){} and everywhere else you can say extern void XYZ().
I have a large project which is designed to control and test hardware.
There are 4 device control classes (for interferometers, a piezo-motor, a PXI system, and a nano-positioning controller).
I created a "master" class called MainIO which stores an instance of each of the above classes, in order to perform operations across the range of IO (i.e. move motor and check interferometers). The MainIO header file includes the 4 control classes headers.
I then have a separate "global" hpp/cpp which contains global variables, conversions, ini file operations and so on. This is laid out with namespaces for the types of operation rather than creating a class, i.e. GCONV::someFunction(); and GMAIN::controllerModel;
I need all 4 control classes to have access to conversion and other global operations. I had them all including global.hpp at one point, but I've changed something (I can't think what it could be!) and now it seems that I cannot include global.hpp in ANY of my control class hpp's or cpp's without getting a linker error -
global.obj:-1: error: LNK2005: "class QString GMAIN::controllerModel" (?controllerModel#GMAIN##3VQString##A) already defined in controllers.obj
I'm absolutely certain that I've done something stupid and the solution is staring me in the face, but it's got to the stage where I'm getting so frustrated with it that I cannot see the wood for the trees.
I have discovered what I was doing wrong, and although it is frustratingly simple, it took me a while to find the relevant documentation to discover my error, and so I will answer my own question in the hope of giving someone else an easier time.
It turns out that in global.hpp I was declaring variables within a namespace like this:
namespace GMAIN {
QString controllerModel;
}
Essentially this means that every file that includes global.hpp will include its own definition of QString controllerModel thereby throwing the linker error. Each control class would have its own definition of the same named variable, violating the one definition rule.
To fix this, QString controllerModel needs to be extern'ed. The extern keyword allows a variable to be declared in multiple locations while only having a single definition (and hence not breaking the rule).
So the working code is now:
//in global.hpp
namespace GMAIN {
extern QString controllerModel; //declaration - this is called for each `#include global.hpp`
}
//in global.cpp
namespace GMAIN {
QString controllerModel; //definition - only called once as .cpp is never included
}
Are you defining controllerModel where you should only be declaring it?
http://www.cprogramming.com/declare_vs_define.html
You should export your dll.
Use __declspec(dllexport). You can include __declspec(dllexport) as a macro in your header file and put the macro in the beginning of each and every member function.
For example:
In your Header.h file include
#define MYMACRO __declspec(dllexport);
and in your class
class classname
{
public:
MYMACRO void MYFUNCTION();
MYMACRO void MYFUNCTION2();
};
My homework assignment is telling me to declare a class inline, but I've only heard of declaring functions inline. What does an inline class declaration do, and how do you achieve it?
I think they are just saying that your classes should go in the header, and for convenience all the class methods should be declared inline in the class itself, instead of putting the class methods out-of-line or into a separate CPP.
It's slightly ambiguous but that's how I'd interpret it.
Comparing functions and classes:
A function can have a declaration and a definition:
ReturnType FunctionName(Parameter1, Parameter2); // a function declaration
ReturnType FunctionName(Parameter1, Parameter2) // a function definition
{
// do something
return ReturnType;
}
The function declaration gives all the information anyone needs who wants to call the function.
The function definition allows the compiler to generate machine code so that when someone calls the function there will be instructions somewhere in the executable that will be called.
This generated code exists only once in the executable. Usually you would put the function definition in a .cpp file (or .c if you're using C, this applies there too), which is compiled and linked into the executable. If that .cpp file isn't linked you will get a linker error saying FunctionName not found or something like that.
If you put the function definition in a header file it is more than likely that the header will be used in multiple places in your system, and included into other .cpp files. This will produce the opposite problem at link time FunctionName already defined in this, that, or the other object file.
So, functions usually aren't defined in header files because the header is usually included in multiple .cpp files so would end up producing duplicated object code.
With classes however it's slightly different. You have two different ways of defining a function for a class. One way is similar to how functions are defined above:
//myleanklass.h
class MyLeanKlass
{
public:
void perform();
};
//myleanklass.cpp
void MyLeanKlass::perform()
{
// Sing, dance, and play the piano
}
Just as with a free function we could have put the definition in the header file, as long as it wasn't included in more than one .cpp file. Otherwise we'd get a similar linker error again void MyLeanKlass::perform already defined ... This scenario is not the norm though. You usually declare classes so that they can be reused through a system. So the header will be included in multiple places and lead to linker errors.
Just to be clear, we could have put the definition in the header file, but not inline. You wouldn't be able to include this header multiple times in your system:
class MyLeanKlass
{
public:
void perform();
};
void MyLeanKlass::perform()
{
// Sing, dance, and play the piano
}
Finally then, we get to the answer to the question. You can define class functions in the header file as long as they are within the class declaration. This is called inline definition. Even if the header is included in multiple .cpp files it won't lead to multiple definitions in compilation units and won't cause linker errors.
//myleanklass.h
class MyLeanKlass
{
public:
void perform()
{
// Sing, dance, and play the piano
}
};
However, there are problems with this approach:
Inlining class functions is likely to make compilation take longer as the compiler will still compile every repeated definition of class functions and only throw away the duplicates at link time.
Making changes to class functions causes a recompilation of any .cpp file which includes it, again leading to longer re-compilation times.
Sometimes it just won't be possible. If a class uses another class and that uses the other class, you're going to have a cyclic dependency and it won't be possible to define everything inline. You can solve that by just putting the problem functions into a separate .cpp file.
I'm having a bit of trouble with a C++ program I'm working on. I've created an abstract class with a single pure virtual method. Since the class has no variables or implemented methods, I've stored the class in a header file without an .cpp implementation file (there isn't any need for one).
The method is:
virtual void handleEvent() = 0;
The issue is when I inherit from that class and implement the method:
virtual void handleEvent(); (.h file)
void handleEvent(){.....} (.cpp file)
I get a compiler error (using g++):
(.rodata._ZtV10Engine[vtable for Engine]+0x8): undefined reference to Engine::handleEvent()
The file is being included in the Engine header class. Any ideas why this isn't working?
I think you forgot to put the class qualifier in the .cpp implementation. It should probably read:
void Engine::handleEvent() { ... }
I'd say deus-ex-machina399 probably has it right, but it could also be your calling conventions (would have to be different compiler settings between at least 2 different .cpp files). Try using __cdecl or __stdcall (or whatever the correct name is for the g++ compiler, try looking at this list)