1
votes

I wanted to use binary_search on my class and so I defined a operator<. It works when everything is in main file, but when I write the class in another file I got linker error.

The simplest example that shows the problem is B.h:

class B
{
public:
~B(void);
string b;
int v;
B(int val, string bb);
friend bool operator< (const B &lhs, const B &rhs);
 };

 bool operator< (const B &lhs, const B &rhs){
    return lhs.v < rhs.v;
};

B.cpp just defines the constructor. Main is sth like this:

#include "B.h"
int main( int argc, const char* argv[] )
{

vector<B> vec;
B a1(2, "gg");
B a2(4, "gdhd");
    vec.push_back(a2);
    vec.push_back(a1);
bool pos = binary_search(vec.begin(),vec.end(), B(2, "ghd"));
}

The error LNK2005: "bool __cdecl operator<(class B const &,class B const &)" (??M@YA_NABVB@@0@Z) already defined in Main.obj : fatal error LNK1169: one or more multiply defined symbols found

How to fix it ?

3
Have you tried separating and respectively putting the function declaration and the function definition into .h and .cpp files?Mark Garcia

3 Answers

3
votes

It's because the operator is improperly defined in the header file. You need to make it inline (or static).

If it's not inline or static, the function will be defined in each source file you include the header file in, leading to multiple definition errors.

2
votes

You're defining the operator function in a header file, which means every .cpp file which includes it gets its own copy. You have two possible solutions:

  1. Mark the function inline.

  2. Move the function into a .cpp file

0
votes

Functions not declared inline must be defined in at most one translation unit. By having B.cpp and the file copntaining main() include the B.hheader, you get two definitions. Conversely, if you declare a function inline, the definition needs to be included in each translation unit where it is used, so having the definition in the header is the right thing to do.

So, if you want the implementation of the operator to stay in the header, you need to use an inline qualifier on its definition - or define the operator directly inside the definition of class B, where you declare it a friend. The latter will make it implicitly inline.

Otherwise you need to move the definition of the operator to the B.cpp file.