1

I'm learning C++, but hit a plateau trying to create a library. Using Visual Studio 2013, I get this error:

Error 1 error LNK2019: unresolved external symbol "public: __thiscall Polynomial::Polynomial(void)" (??0Polynomial@@QAE@XZ) referenced in function _main A:\Medier\Desktop\PolyLib\Test\Test.obj Test

The testproject is currently cut down to this:

#include "A:\Medier\Desktop\PolyLib\PolyLib\PolyLib.h"

using namespace std;

void main()
{
    Polynomial poly;
}

The library header file, PolyLib.h, looks like this:

using namespace std;

class Polynomial {

private:
    double* Coefficients;  //Array of coefficients - Pointer type.
    int Degree; //The highest exponent of the polynomial

public:
    Polynomial(); //Default constructor - Creates the trivial polynomial 0.
    Polynomial(int degree, double coefficients[]); //Constructor for specific polynomials

Finally there's a CPP file in the library, PolyLib.cpp, providing implementations for the header file. Looks like this:

#include "PolyLib.h"

using namespace std;

Polynomial::Polynomial() {
    Degree = 0;
    Coefficients = new double[Degree + 1];
    Coefficients[0] = 0;
}

Polynomial::Polynomial(int degree, double coefficients[]) : Degree(degree), Coefficients(coefficients) {
    int i = 0;

}

I understand that my test project looks to the PolyLib.h file to see what stuff is available. And I understand the error says it can't find the actual implementation of the empty constructor for Polynomial. As such I conclude that the PolyLib.cpp file is not being used.

Can anyone tell me where I go from here?

Treeline
  • 475
  • 1
  • 8
  • 23
  • 1
    Placing `using namespace std;` is header files is a **bad** idea. It's not the source of your problem but you still shouldn't do it. – Captain Obvlious Jun 03 '15 at 22:53
  • You're probably right, but can I ask why? **Edit** - Google had plenty of answers, nevermind. :) – Treeline Jun 03 '15 at 22:54
  • 1
    See http://stackoverflow.com/questions/14575799/using-namespace-std-in-a-header-file – Captain Obvlious Jun 03 '15 at 22:55
  • 1
    Static libs need to be explicitly added to the project by name. If you are building PolyLib.lib, then from your other project you'd need to link PolyLib.lib in the list of libs. As well as update the lib search path. – VoidStar Jun 03 '15 at 22:58
  • Initially i spent an hour trying to link the library to my project correctly, and thought I finally had it right. Can you explain thoroughly how I make the test project use PolyLib.lib? – Treeline Jun 03 '15 at 23:02
  • 1
    I posted an answer (and example file) below. – VoidStar Jun 03 '15 at 23:32
  • 1
    Can you verify if you are *trying* to have a separate .lib file? Or are you just trying to build the .cpps files together in one project? If you are trying to do this as one project, the most likely explanation is that `PolyLib.cpp` has been somehow excluded from the project. Right click the file, go to properties, and verify that it is not excluded. – VoidStar Jun 03 '15 at 23:45
  • I'm giving it a try, hang on. – Treeline Jun 03 '15 at 23:45
  • Okay, I'm getting even more confused. Your library works. Using your function prints "3" as expected. So I figured that my project might have been messed up somehow, given that I tried lots of stuff by now. My project had exactly the same structure as yours, so I tried copying my code into your project, with no other changes. I even left your function "myfunction" there. Both main.cpp and header.h seems OK, but source.cpp does not recognize Polynomial as anything. "myfunction" is recognized. The error I get is "IntelliSense: name followed by '::' must be a class or namespace name". – Treeline Jun 04 '15 at 00:04
  • 1
    Sounds like PolyLib.h didn't get included in that source file? – VoidStar Jun 04 '15 at 00:11
  • You are right, I am getting tired. Added "#include "header.h"" as the first line in source.cpp. It then says "IntelliSense: cannot open source file "header.h" a:\Medier\Desktop\LibExample\LibExample\source.cpp". That means it does not know where to look for the header file, correct? – Treeline Jun 04 '15 at 00:16
  • And finally! http://stackoverflow.com/a/9754017/4600745 explained that I had to use an absolute path for referencing header.h - It works now. Thank you for all your help. This could have taken far longer if not for you. – Treeline Jun 04 '15 at 00:29

2 Answers2

1

If you are trying to build Polylib.h and Polylib.cpp into a binary such as Polylib.lib then you need to have a separate project that has these source files and builds a static library. Then you need your project to link this Polylib library so that it can link the code into your binary. If you just want to have one project and only build one binary then you need to move the Polylib.h and Polylib.cpp source into your project and build it all together. Another thing is that using absolute paths for including headers is a bad idea. You want to include headers using relative pathing and then use the project settings to tell it where the headers are located. For example if its local to the project then use #include "header". If its not local to the project then use #include <libraryfolder/header> and then tell the project where the library folder is in the "include directories setting".

Bill
  • 14,257
  • 4
  • 43
  • 55
Josh Edwards
  • 369
  • 1
  • 4
1

It is possible to build all of your .cpps into a single project, which is most common for beginners. However, from the question tags and wording, I'm assuming you want to create and link a static lib, which can also be done fairly simply.

I just constructed an example of a properly set up static lib + exe linking in one VS2013 project: Dropbox link, for the purposes of explaining this question.

The basics are that you need two projects: A lib project (outputs a static .lib file) and an exe project (outputs an .exe file). The .exe project contains a main() function, and is able to include headers and link to the .lib.

The points of interest in MyExe are that I added $(SolutionDir)\LibExample\Inc to the include path in order to include my header (header.h), and I added $(SolutionDir)\$(Configuration) to the lib path for the libraries. You can find these by right clicking the project, go to properties, and it's all under "VC++ Directories".

A great tip about determining the path needed to find your lib is to simply build the lib. It actually tells you in the "Output->Build" text spew where the file it just built is located. This is the path that you need. $(SolutionDir)\$(Configuration) is the "macro" shorthand of this path. I recommend using the macros so you can move your project directory to another path or computer easily.

I also added LibExample.lib; to "additional dependencies" in the linker\input settings. This is the key step for being able to link the lib. Not doing this will result in an unresolved external symbol, just like you're seeing.

I also set a dependency between MyExe and LibExample (you right click the project, Build Dependencies->Project Dependencies). This is important so you can rebuild the entire solution without worry of linking to the older version of the lib. With the dependency in place, it will always build the lib first, then the exe.

VoidStar
  • 5,241
  • 1
  • 31
  • 45