Click here to Skip to main content
16,016,814 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hey guys,

I have a header file of math functions I've created and I want to use it in class1.cpp. When I don't include it I get the following errors:

VB
1>Output.cpp(465): error C3861: 'createRot': identifier not found
1>Output.cpp(471): error C3861: 'createRot': identifier not found
1>Output.cpp(477): error C3861: 'createRot': identifier not found


but when I include the header file I get the following errors:

VB
1>RTClientExample.obj : error LNK2005: "double * __cdecl crossProd(double * const,double * const)" (?crossProd@@YAPANQAN0@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl createTrans(double * const,double (*)[3],double (*)[4])" (?createTrans@@YAXQANPAY02NPAY03N@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl createRot(double * const,double * const,double * const,double (*)[3])" (?createRot@@YAXQAN00PAY02N@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl rotVect(double *,double (*)[3],double * const)" (?rotVect@@YAXPANPAY02NQAN@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl transpose(double (*)[3])" (?transpose@@YAXPAY02N@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl matMult(double (*)[3],double (*)[3],double (*)[3])" (?matMult@@YAXPAY02N00@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl matMult(double * const,double (*)[3],double *)" (?matMult@@YAXQANPAY02NPAN@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl angle(double * const,double * const,double *)" (?angle@@YAXQAN0PAN@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "int __cdecl round(double)" (?round@@YAHN@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl printTrans(double (*)[4])" (?printTrans@@YAXPAY03N@Z) already defined in Output.obj
1>RTClientExample.obj : error LNK2005: "void __cdecl printRot(double (*)[3])" (?printRot@@YAXPAY02N@Z) already defined in Output.obj


As you ladies and gentlemen can see, in this case it tells me that it's already defined in class1.obj

I'm sure it's a dumb mistake but I'm not really sure what that mistake may be. Could someone clear this up for me? As a final note, I have used this file before and it works just fine.

Don
Posted
Updated 26-Jul-11 4:52am
v2
Comments
Richard MacCutchan 26-Jul-11 11:04am    
Let's see your header file, it may be that you are instantiating something in the header and then including it in RTClientExample as well as Output.
Donald Hume 26-Jul-11 11:38am    
So this is all that's at the top of my header:
#include <iostream>
using namespace std;

#define PI 3.14159265

I tried using include guards as suggested by SA:
#ifndef IOSTREAM
#include lessthan iostream greaterthan

using namespace std;
#define IOSTREAM


#endif


#ifndef PI
#define PI 3.14159265
#endif

But I seem to be throwing the same linker errors.
Richard MacCutchan 26-Jul-11 13:10pm    
I can't believe that this is your header file, since it does not contain a definition of createRot, which is the identifier that is supposedly fixed by including it. Also your header guard is wrong it should surround everything else, you want to add something like the following:

#ifndef MYHEADER_ID
#define MYHEADER_ID
.. all of your header information goes here
#endif

Looks like you defined the functions right in your header. For example, like this:
// file foo.h
void foo() {
   puts "Hello World!");
}

// file foo.cpp
#include "foo.h"

//file bar.cpp
#include "foo.h"

Note that #include is a preprocessor command, causing the preprocessor to copy the whole text contained in foo.h into each of the cpp file including it, so, after the prprocessor is done, the intermediate cpp files that you get look like this:
// file foo.cpp after preprocessor step
void foo() {
   puts("Hello World!");
}

// file bar.cpp after preprocessor step
void foo() {
   puts("Hello World!");
}

Now the compiler takes the processed version of foo.cpp, finds the function with the signature void foo(), and stores the signature of this function as well as the address of the binary code that it starts. Then the compiler picks the processed version of bar.cpp and does the same, ignorant of the code that went into foo.obj (no, the compiler does not keep track of other compiled modules!).

Then the linker steps up, and binds all modules into one executable. To do so it needs to create a table of all functions and the memory offsets to the start of these functions within the binary code. It picks up foo,obj and registers the function with the signature void foo(). Then it picks up bar.obj and tries to register the function foo() it finds there, but notices that a function by that signature already exists! Since the linker does not know whether the two versions of the binaries are identical, and it isn't clear which function to call, the linker, by itself cannot resolve this issue. Hence it issues the error, LNK2005.

There are a few exceptions: If you define a function as inline, then the preprocessor will not put the whole function into the source file that include the header, but instead will replace all calls to the function with the code of the functions body, much like a #define macro (but a lot safer). It also seems that defining member functions of a class right at the point where they are declared is also possible, although I am not sure if this is due to them being interpreted as inline, or whether functional code form classes is treated differently.

In short, you should not define functions in a header file! A header file is meant for declarations only. Move the definitions to a separate cpp file instead and your problem should be solved.
 
Share this answer
 
Comments
Donald Hume 26-Jul-11 13:12pm    
I do believe this is a well thought out and formulated response. Thank you so much for your time Stefan.
Stefan_Lang 27-Jul-11 3:07am    
You're welcome. Although this turned out much longer than intended. I've come across this particular error quite a few times, but when I tried to formulate an answer I realized I never considered, *why* the linker couldn't resolve this be itself, so the explanation I worked out was as much to my own benefit as yours. ;)
Manfred Rudolf Bihy 26-Jul-11 14:13pm    
Great effort, well explained!
Can only give 5+
Stefan_Lang 27-Jul-11 3:08am    
Thank you.
Sergey Alexandrovich Kryukov 26-Jul-11 21:18pm    
Good idea; it could happen, my 5.
--SA
Pay attention: first bunch of errors from compiler, but second one from the linker; and the symbols are different. It means that you try to link in the same symbol(s) twice: once is some library or object file you're linking in (compiled before), another time in the object file which you compile during build.

Use some binary dump and/or documentation to see what symbols are defined on what libraries, such as DUMPBIN.EXE. This utility is bundled with all versions of Visual Studio and can be run via Visual Studio Command Prompt, see the reference here: http://msdn.microsoft.com/en-us/library/c1h23y6c%28v=vs.71%29.aspx[^].

Just in case, make sure you always use proper include guards in all your include files, see http://en.wikipedia.org/wiki/Include_guard[^]. However, I think the problem is in using your library.

—SA
 
Share this answer
 
Comments
Harrison H 26-Jul-11 21:17pm    
Perfect. Don't forget to add that including "using namespace x" in the header is a big no no.
Though it is not recommended .... one quick fix is

if you are using Visual studio,

Go to ProjectProperties->ConfigurationProperties->Linker->Command Line

Add following line to the Additional Options

/FORCE



This option will force the linker to take one of the available definitions.
 
Share this answer
 
v3
Comments
Stefan_Lang 27-Jul-11 3:14am    
This presumes an error of the kind I described in my solution, in which case the right solution is to move the function definitions in question to a cpp file.

The only other case for this linker error that could be 'solved' with the method you suggest is when there are two functions with the same signature defined in different cpp files - and in that case it's a pretty bad idea to force the link, as there is a chance the 'wrong' implementation is being used if the two versions aren't identical copies. In that case, the correct solution is to check out the cpp files for duplicate function definitions and either eliminate or rename (or otherwise change the signature of) one of them.
PrafullaVedante 27-Jul-11 4:38am    
Yupp. Agreed.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900