views:

390

answers:

2

I have a header file in a library (alibrary.lib). The library is a static library (.lib) and it links properly to exe.

Now, I have a class: Vector3d.

class Vector3d 
{
    void amethod()
    {
       blah
    }

};

Vector3d cross(const Vector3d &v0, const Vector3d &v1) 
{
      float x,y,z;

      x = v0.y*v1.z-v0.z*v1.y;
      y = v0.z*v1.x-v0.x*v1.z;
      z = v0.x*v1.y-v0.y*v1.x;

     return Vector3d(x,y,z);

}

Vector3d is declared and defined in a header file (Vector3d .h). After the class declaration, I the cross function.

The lib compile is file, but when it links to the unit test exe I get this error:

 flywindow.obj :error LNK2005: "class Vector3d __cdecl cross(class Vector3d const &,class Vector3d const &)" (?cross@@YA?AVVector3d@@ABV1@0@Z) already defined in fly.obj

Any ideas?

Thanks

+1  A: 

The most likely explanation is that you've got code (specifically the definition of cross) in your include file and your include file is being included by two source files, hence the double definition.

Header files should have declarations in them, not definitions. Declarations (syaing that something exists) are things like typedef's, class declarations, enum's and so on.

Definitions (giving meaning to thos things that exist) are things like functions, varialble definitions and so on.

Your cross function should be declared in the header file:

Vector3d cross(const Vector3d &v0, const Vector3d &v1);

but defined in a separate source file.

paxdiablo
+2  A: 

If you define a free (not a member of a class) function, it has to be defined in a .cpp file separately compiled, or in a header and marked inline. So in your case, you can get away making it compile by this:

inline Vector3d cross(const Vector3d &v0, const Vector3d &v1) {
      float x,y,z;

      x = v0.y*v1.z-v0.z*v1.y;
      y = v0.z*v1.x-v0.x*v1.z;
      z = v0.x*v1.y-v0.y*v1.x;

     return Vector3d(x,y,z);

}

The error is caused because you have the definition of the function in the header, but haven't marked it inline. If you now include that header into two files that are compiled separately, the linker, when trying to link the compiled object files, will throw out an error, because it then sees a cross function being defined twice.

It works without exlicitly putting inline for member functions of a class, because member functions that are defined inside the class definition are implicitly inline.

It is however, not a good idea generally to make function definitions in the header. If your function would depend on other types than just the vector (in your case it's fine IMHO, but it's debatable of course - some people don't like it), then you would be required to include the headers for those types. That will unnecessarily bloat the code that's indirectly included by your header. Instead, in those cases you would solely put only a declaration of your function inside the header:

Vector3d cross(const Vector3d &v0, const Vector3d &v1);

But define it within the .cpp file that's compiled separately. The inline, of course, should then be dropped.


Let me add a small list of definitions and declarations, just to help in keeping things clear about what declaration and definition means for functions and classes. Note that every definition is also a declaration, but not the other way around:

// class _declaration_ of boo
class boo;

// class _definition_ of foo.
class foo {
    // member function _declaration_ of bar
    void bar();

    // member function _definition_ of baz
    void baz() { }
};

// function _definition_ of fuzz
inline void fuzz() { }

// function _declaration_ of fezz
void fezz();
Johannes Schaub - litb
inline worked. thanks
cbrulak