0

How come when I have the same sort algorithm, as such

bool Sorter(const Object* n1, const Object* n2) { return (n1->GetValue() < n2->GetValue()); }

in separate .cpp files the linker (l believe) gives me a multiply defined symbol -error? When I rename them (Sorter1, Sorter2, ..) it compiles. These classes are inherited from the same parent class but the parent has no algorithm stuff in there. I just fail to realize why this becomes an error when the classes have no direct contact to each other and am curious.

Also, is there any direct way of referencing sorters from say, a parent class, or do I just have to create a function which uses the sorter?

Susie
  • 5,038
  • 10
  • 53
  • 74
deprecated
  • 57
  • 1
  • 7
  • You are breaking the [one definition rule](http://en.wikipedia.org/wiki/One_Definition_Rule). The linker is right to complain. Concerning how to fix it, I think more details or some sample code is needed. – juanchopanza Sep 10 '12 at 20:33

4 Answers4

3

By default a function has external linkage, meaning any source file that has a declaration of the function can use it no matter which file has the definition. The linker is responsible for connecting the different uses, which is why it complains when it finds more than one.

To keep a function private to the source file it's contained in you must use the static keyword on it or put it in an unnamed namespace.

If all the function definitions are identical you can use the inline keyword to indicate to the linker that they are identical, but in that case you should put the function into a header file to be completely safe.

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

try writing it as

static bool Sorter(const Object* n1, const Object* n2) { 
  return (n1->GetValue() < n2->GetValue()); 
}

or

namespace { 
  Sorter(const Object* n1, const Object* n2) {  
     return (n1->GetValue() < n2->GetValue()); 
  }
}

This should give it the per-cpp scope you're looking for.

if you're writing the function inside a header file, use

inline bool Sorter(const Object* n1, const Object* n2) { 
  return (n1->GetValue() < n2->GetValue()); 
}
Grim Fandango
  • 2,296
  • 1
  • 19
  • 27
0

Those seem to be free functions, not members of a class. To define a class member, you'd need bool Class1::Sorter( blah ) { foo; } and bool Class2::Sorter(blah) { foo; }

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • If I do this then I also need to define it in the header file making it more like a regular function syntax. Using the static keyword like Mr. Ransom said serves my purpose better here. – deprecated Sep 11 '12 at 09:24
  • Excellent. There wasn't much info in the original post, so I assumed you had already defined them in the header file. – Robᵩ Sep 11 '12 at 15:19
-1

Sorter is a global function -- not a class or an object instantiated from a class. If the same global function is declared in two compilation units, you will get a linkage error.

bspikol
  • 96
  • 6
  • @DeadMG: What is a UB? I don't understand your comment. Thanks. – bspikol Sep 10 '12 at 21:14
  • UB is Undefined Behaviour, although I must admit it's news to me that breaking the One Definition Rule results in UB. For global functions I would certainly except a linker error as you say. – john Sep 10 '12 at 21:18
  • @john - the ODR applies to **many** situations. One where undefined behavior is most obvious is having two different definitions of the same class. If you pass an object created with one definition to code that expects the other, all kinds of exciting things can happen. – Pete Becker Sep 11 '12 at 10:19