I have a Visual C++ solution with 2 projects: rectangle and project3.
In rectangle project I have rect.cpp and rect.h.
rect.h
#ifndef rect_h
#define rect_h
class Rect
{
public:
Rect();
int m_h;
int m_w;
};
#endif //rect_h
rect.cpp
#include "rect.h"
Rect::Rect()
{
m_h = 1;
m_w = 5;
}
whenever I try to create rect object from the rectangle project it succeeds.
But when I try to do the same from the project3 it produces a linker error.
LNK2019: unresolved external symbol "public: __thiscall
Rect::Rect(void)" (??0Rect##QAE#XZ) referenced in function _main
1>C:\Users\mbaro\documents\visual studio
2017\Projects\Project2\Debug\Project3.exe : fatal error LNK1120: 1
unresolved externals
main.cpp (in project 3)
#include "rect.h"
using namespace std;
int main()
{
Rect* a = new Rect();
return 0;
}
I kind of feel that class definition is picked up successfully, but the linker can not link the constructor code from rect.cpp.
What is the problem and how to solve it?
Thanks.
The error is normal: you told the compiler where it could find the .h files, but you did not tell the linker where it could find the .obj files.
It may depend on the exact VS version, but in Project/Properties, you should find Linker/Input and there Additional dependencies. If you only need one or two object files (xxx.obj) from the other project, add them here. That way, you avoid code duplication, which will be a nightmare for future maintenance...
If you have many common files, you should considere to put them in an auxilliary project that would build a (static)library in the same solution, and then link the library in both project (and of course give access to header files of the library project for the other projects using the library).
I have already started writing a long, long answer. Then i realized, what You may be missing is that despite Your class is named "Person" the header file You should have added is named "rect.h".
Also Your constructor cannot have a declaration of values in the header file (EDIT:not true, I was mistaken). In the header file, try using:
Person(int h, int w);
You declare what will be needed, not what You already have. If You want those to be specifically what You wrote the constructor should be:
Person();
in .h
and
Person::Person()
{
m_h = 1;
m_w = 5;
}
in .cpp.
If You need more detailed description of using include, I have already written a big part of it, so don't hesitate to ask.
Related
Similar to LNK2005 Error in CLR Windows Form, yet this answer cannot explain what I've met.
My question is at the end of the description, thanks for the patience.
The project structure is as below (I simplify the situation to demonstrate the problem I met, which does not make any sense in real development):
Environment: Visual Studio 2019
Configuration: Debug/x86
OpenCV 420: I compile it to a dynamic library (.lib+.dll) myself because the x86 version is not provided officially.
Project2: pure C++, output type: lib
// ClassB.h
#pragma once
#include <opencv2/opencv.hpp>
class ClassB
{
public:
void FuncB();
};
// ClassB.cpp
#include "ClassB.h"
void ClassB::FuncB() {
cv::Mat mat;
}
Project3: C++ with /clr on, output type: dll for .NET Framework v4.6.1
// ClassC.h
#pragma once
#include <iostream>
#include <opencv2/opencv.hpp>
class __declspec(dllexport) ClassC
{
};
// ClassC.cpp
#include "ClassC.h"
Link against (the input libs order matters, will explain later)
opencv_world420d.lib (it's just an import library, at runtime use opencv_world420d.dll)
Project2.lib
And the compiler throws errors:
LNK2005 "public: __thiscall cv::MatSize::MatSize(int *)" (??0MatSize#cv##QAE#PAH#Z) already defined in opencv_world420d.lib(opencv_world420d.dll) Project3 (ClassB.obj) 1
LNK2005 "public: __thiscall cv::MatStep::MatStep(unsigned int)" (??0MatStep#cv##QAE#I#Z) already defined in opencv_world420d.lib(opencv_world420d.dll) Project3 (ClassB.obj) 1
After some digging, I suppose it is because there're some inline functions in mat.inl.hpp header file which is needed by class Mat and included byopencv.hpp(indirectly though), as below:
inline
MatStep::MatStep(size_t s)
{
p = buf; p[0] = s; p[1] = 0;
}
Maybe the compiler decided not to inline the functions, but indexed them into Project2.lib, to assure, I dump the two libs:
// Project2.lib
8B6 00000000 SECT109 notype () External | ??0MatSize#cv##QAE#PAH#Z (public: __thiscall cv::MatSize::MatSize(int *))
// opencv_world420d.lib
??0MatSize#cv##QAE#PAH#Z (public: __thiscall cv::MatSize::MatSize(int *))
As far as I know, SECT109 and External do mean that Project2.lib has complete definition of cv::MatSize::MatSize(int *), so do opencv_420world420d.lib
However, I explore 3 separate ways out to pass the compilation
Solution 1
swap the linking order to:
Project2.lib
opencv_world420d.lib
Solution 2
Turn the Project3 /clr off, make it a pure C++ project
Solution 3
MakeClassB::FuncBinline:
// ClassB.h
#pragma once
#include <opencv2/opencv.hpp>
class ClassB
{
public:
void FuncB() {
cv::Mat mat(100, 200, CV_8U);
}
};
// ClassB.cpp
#include "ClassB.h"
For solution1/2, I don't even touch Project2, so obviously ??0MatSize#cv##QAE#PAH#Z still exists in Project2.lib (so I don't understand how the compilation succeed).
For solution3, ??0MatSize#cv##QAE#PAH#Z disappears in Project2.lib (again I dumped the lib file and search the function name), so this does make sense to me.
In conclusion, my questions are:
Why solution 1 works, by just swapping the input libs order?
Why solution 2 works, by just switching off /clr for Project3 whose output target is dll?
OpenCV puts inline implementation in their hpp file, I wonder if it is a safe and good way to do so?
Today I downloaded the new version of visual studio, and I tried to build a class:
class Fraction
{
public:
Fraction(int, int);
private:
int _a;
int _b;
};
I also built a cpp file for the implementation:
#pragma once
#include "Fraction.h"
#include <string>
Fraction::Fraction(int a, int b)
{
_a = a;
_b = b;
}
The header file (thc class) is in file called "Franctions.h" and found in the header files directory.
The cpp file (thc class) is in file called "Franctions.cpp" and found in the Resource files directory.
When Im trying to run this simple program, I get this issue:
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "public: __thiscall Fraction::Fraction(int,int)" (??0Fraction##QAE#HH#Z) referenced in function _main Homework2 c:\Users\VVV\documents\visual studio 2017\Projects\Homework2\Homework2\questionA.obj 1
Why can it be happening?
EDIT:
main:
#include "Fraction.h"
int main()
{
Fraction f1(1, 2);
return 0;
}
The problem is not within your Fractions.h or Fractions.cpp, but rather with questionA.cpp note that the referencing file that cannot find the symbol in the error is:
c:\Users\VVV\documents\visual studio 2017\Projects\Homework2\Homework2\questionA.obj
Is #include "Fractions.h" in that file?
this error means that the compiler can't find this function.
write the specific place in the include path and see if it solve your problem.
if so, it means your header file is looking at different directory than the one you think.
Is there something special about how an MFC project handles includes?
Here's the scenario. I like to define my class member functions in the h file, instead of splitting up a class between two files.
In Visual Studio I can create an empty Win32 project and do something like this:
main.cpp:
#include "doubleDef.h"
int main()
{
doubleDef t;
t.func();
return 0;
}
doubleDef.h:
#pragma once
class doubleDef
{
public:
int func();
};
int doubleDef::func()
{
return 4;
}
This builds just fine.
If I take doubleDef.h into an MFC dialog project, and add #include "doubleDef.h" to the h file of the main dialog, I get LNK2005, saying that func is already defined, making it seem as if the #pragma once is being ignored.
If I instead include doubleDef.h in the main dialog's cpp file, everything is fine. But in the empty Win32 I can include doubleDef.h "multiple times" by doing this:
Header.h
#pragma once
#include "doubleDef.h"
Header1.h
#pragma once
#include "doubleDef.h"
main.cpp:
#include "Header.h"
#include "Header1.h"
int main()
{
doubleDef t;
t.func();
return 0;
}
That is, it appears #pragma once works as expected (prevents multiple definitions of doubleDef::func()).
If I turn doubleDef into a template class, then the function definition must be in the h file. Likewise, I can make func inline, either by adding the keyword or implicitly by defining it next to the declaration in the class (as in int func() {return 4;}), and then, again the definition must be in the h file.
According to the documentation, the compiler treats inline as more or less optional, so it seems like if I just want to keep everything in the h file, I can just make everything inline.
What gives?
The #pragma once means the file will only be included once per source file. If you have many source files including it, you will still get a copy in each source file.
By declaring a function inline, you tell the compiler it's OK to have multiple copies - as long as those copies are identical.
The usual way of working is to have the declarations in the header file, and the definitions (implementation) in another source file.
P.S. MFC has nothing to do with your problems.
In your simple Win32 project you have one main file that keeps including the same item, basically a no-op. To have multiple of the same include in referenced in the same file does not create a new link.
However with your MFC project you put your header file into mainfrm.h. That file is included in several other files in that project not just the mainfrm.cpp. Essentially creating a new link for each of those other files the main header was included in.
1>MainFrm.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>FileView.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>ClassView.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>OutputWnd.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>PropertiesWnd.obj : error LNK2005: "public: int
__thiscall doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in MfcTest.obj
Take a look at that output. You can see each of the other components that thinks it has that object.
To put it another way your original statement of why does it work for one way and not the other is because the complexity of the second example (MFC) actually includes that header all over the place. If you only want it used by the main form then include it in the cpp for it.
This was already answered before, here is more detailed explanation:
You cannot define a function more than once, unless it is inline
You cannot declare a function more than once in the same file.
You do need to declare functions and classes multiple times if they are referenced in multiple .cpp files.
#pragma once prevents multiple declarations in the same file. It will not prevent multiple declarations in different files. Multiple declarations is exactly what you want and it is why you are including the files in multiple .cpp files in the first place.
class N1 {
public:
//Declaration
//Multiple .cpp files need to know about this class and its members
int foo();
};
//Definition
//should be done once. This should go to .cpp file
int N1::foo() {
return 1;
}
In the above example, compile will work fine in multiple .cpp file. The compile routine does not notice multiple definitions. But the linker notices multiple definitions and complains. You have to move the definition to .cpp file or use inline functions.
class N2
{
public:
int foo();
};
inline int N2::foo()
{ //valid, even if it is repeated in different files
return 1;
}
class N3
{
public:
int foo() //always valid
{
return 1;
}
};
I have read this informative stackoverflow question regarding unresolved external symbols, but I am still not sure how to solve my issue.
Within Visual Studio 2012, I have a solution consisting of multiple projects, one of which is a static library called common. Each project that produces an executable consists of a header and associated cpp file of all global functions used throughout that specific program, called programglobals. In the process of developing one of these projects, I started duplicating some of this code from one project's programglobals to another. Now that I have completed all the projects, I want to extract the duplicate code into a associated header and cpp file within the common library, but I believe I might be referencing them incorrectly, which is producing these unresolved external symbol errors
Here is a dumbed down example of what I am currently attempting.
Common Library Files
//solutionglobals.h
void commonFunction();
//solutionglobals.cpp
void commonFunction() {
int asdf;
}
Project A Files
// programglobals.h
#include "../common/solutionglobals.h
void functionUsedInProjectA();
// programglobals.cpp
void functionUsedInProjectA() {
int x;
}
// output.h
#include "programglobals.h"
void asdfA();
// output.cpp
void asdfA() {
int x;
functionUsedInProjectA();
commonFunction();
}
Project B Files
// programglobals.h
#include "../common/solutionglobals.h
void functionUsedInProjectB();
// programglobals.cpp
void functionUsedInProjectB() {
int x;
}
// output.h
#include "programglobals.h"
void asdfB();
// output.cpp
void asdfB() {
int x;
functionUsedInProjectB();
commonFunction();
}
Any reference to commonFunction() results in an unresolved external symbol error.
Thanks!
You will have to specify in your executable projects that they reference the static lib. May be http://msdn.microsoft.com/en-us/library/vstudio/ms235627%28v=vs.110%29.aspx#uselibinapp helps (lower third of the article).
Before you can use the math routines in the static library, you must
reference it. To do this, open the shortcut menu for the MyExecRefsLib
project in Solution Explorer, and then choose References. In the
MyExecRefsLib Property Pages dialog box, expand the Common Properties
node, select Framework and References, and then choose the Add New
Reference button.
The linker cannot 'see' your function and as such thinks that it does not have an external symbol referencing it, hence the error.
You must #pragma comment(lib, [library here]) to reference the external function.
The following code can be used to reproduce this error:
[header file- test.h]:
#include "StdAfx.h"
void someOtherFunction();
void someFunction(string thisVar);
[code file- test.cpp]:
#include "StdAfx.h"
#include "test.h"
void someOtherFunction()
{
printf("Hello World!");
}
[function body for someFunction(string thisVar) is missing!]
I'm getting this error from the linker:
1>PACBalancesTest.obj : error LNK2001: unresolved external symbol "public: bool __thiscall PAC::BalChgKeyComparator::operator()(class PAC::BalChgKey const &,class PAC::BalChgKey const &)const " (??RBalChgKeyComparator#PAC##QBE_NABVBalChgKey#1#0#Z)
I must be missing something really obvious, because I've looked at the definition of the "missing" symbol repeatedly and can't see any problem.
The symbol's definition is in a .lib file. I see the following in the output from dumpbin /symbols on that .lib file:
2F0 00000000 SECTFD notype () External | ??RBalChgKeyComparator#PAC##QBE_NABVBalChgKey#1#0#Z (public: bool __thiscall PAC::BalChgKeyComparator::operator()(class PAC::BalChgKey const &,class PAC::BalChgKey const &)const )
And there are other symbols being resolved successfully from that .lib file! (In fact, from the same .obj.) [Update: I no longer think the preceding statement is true. This may be my first attempt to access any function not defined in a .h file.]
WHAT FOLLOWS IS NOT RELEVANT TO THE PROBLEM -- SO PLEASE DON'T SPEND TIME STUDYING IT!
Here's the declaration of the function (in PACBalances.h):
namespace PAC {
class BalChgKey {
public:
...
};
struct BalChgKeyComparator {
bool operator()(const BalChgKey& lhs, const BalChgKey& rhs) const;
};
typedef std::multimap<BalChgKey, long, BalChgKeyComparator> BalChgKeyLongMMap;
};
Note that I've tried changing 'struct' above to 'class', with no effect.
Here is the calling code (in a cpputest test file):
#include "CppUTest/TestHarness.h"
#include <utility>
#include <map>
#include "PACBalances.h"
using namespace PAC;
...
TEST_GROUP(PACBalanceCUMap)
{
BalChgKeyLongMMap empty;
BalChgKeyLongMMap onesy;
void setup()
{
// **Adding the following line caused this error to start to occur.**
onesy.insert(std::pair<BalChgKey, long>(BalChgKey(BOPCAT_FEE, PAYMTYPE_OVERDRAFT_FEE, 4321, 41100, 1, 17), 17));
}
void breakdown()
{
}
};
And here is the definition of the operator function itself:
bool PAC::BalChgKeyComparator::operator()(
const BalChgKey& thing1,
const BalChgKey& thing2
) const
{
if (thing1.m_balKey.m_balCat < thing2.m_balKey.m_balCat) return true;
else if (thing1.m_balKey.m_balCat > thing2.m_balKey.m_balCat) return false;
// Fall thru if balCats are equal
...
return false;
}
Please note that:
The comparator, and the typedef'd multimap, works beautifully in lots of code (not shown above).
The test file calls lots of other functions declared and defined in that .h file, but this is the first time I've tried calling a function defined in a separate .cpp file.
My question is not why does the 'onesy.insert' call requires the comparator function. I understand that. It just happens to be the first multimap operation that I've coded in the test set that actually uses the comparator.
I have various hunches, but I'm running out of them, so if someone who knows about this stuff can give me any leads I would be very grateful.
Norm
#panta rei: You provided the key in your comment. (Sorry, can't figure out how to type Greek letters here.)
The problem was basically that I didn't know how to tell Visual Studio what objects to link in. I had told my solution that AnalyticsUTest depended on AnalysticsUTested, but the linking step is performed by the project (AnalyticsUTest), not the solution, so I needed to tell the project to include this .lib file.
So I went to the project's properties sheet and created two new macros, one giving the folder where VS was putting my .lib file (ANALYTICSUTESTED_LIB_PATHS), the other giving the name of my .lib file (ANALYTICSUTESTED_LIB_DEPENDENCIES) -- both by analogy with the CPPUTEST_LIB* macros.
And then I added $(ANALYTICSUTESTED_LIB_PATHS) to Linker > General > Additional Library Directories. And I added $(ANALYTICSUTESTED_LIB_DEPENDENCIES) to Linker > Input > Additional Dependencies.
And that fixed my problem! (I've spelled it out here in case another newbie like me comes along and needs it.)
Thank you, panta rei. How do I give you points for an answer provided via a comment?