Question

I have defined a function within a header file. In debug, it compiles and links fine. In release, I get the compile error "multiple definition of `blah::blah(blah& blah)'" for every object file of every class that includes the header.

I'm using gcc-4.8.1. I can't post up the actual code, this version has names changed to protect the innocent:

#ifndef INCLUDE_SMELLS_FUNNY
#define INCLUDE_SMELLS_FUNNY

#include "ParentClass.h"
#include "ChildClassA.h"
#include "ChildClassB.h"

namespace someplace {

bool smellsFunny(const ParentClass& someData) {

  // All ChildClass As smell funny
  if(dynamic_cast<const ChildClassA*>(&someData)) {
    return true;
  }

  // If ChildClass B, need to check if smells funny
  const ChildClassB* childB = dynamic_cast<const ChildClassB*>(&someData)
   if(childB) {
    return childB->MoreThanAWeekOld();
  }

  // Default is smells OK
  return false;
}

}

#endif // INCLUDE_SMELLS_FUNNY

I haven't been able to find which gcc flag is responsible. Of course, a fix is just to move the implementation into a cpp file. But why is this necessary? Why does this happen only in release?

Was it helpful?

Solution 3

I can not say exactly but maybe in the debug mode the function is considered as inline function.

OTHER TIPS

It's because you define the function in a header file, and then include that header file in multiple source files. That means the function will be defined in each source file (technically, translation unit) where you include the header.

There are a couple of solutions to this:

  1. Mark the function as static. That means that each definition in the translation units will not be exported.
  2. Mark the function as inline. This works basically the same as the first alternative.
  3. Put the definition of the function in a source file, and only have its declaration in the header file.

For a small function like the one you have, then alternative 2 might be a good one. If you have a larger function, that can't easily be inlined, you should go with alternative 3.

Also, if you go with number 3, then you don't need to include the header files, and then lessen the risk of circular inclusion.

Since you have placed the function definition in the header, you need to mark it inline:

inline bool smellsFunny(const ParentClass& someData) { ...

This is because every place in which you include the header will have a definition of the function, breaking the one definition rule (ODR). inline lets you work around the ODR.

As to why there is no problem in release mode, that doesn't make sense: the code is not correct. It could be that release mode is declaring the function inline for you.

If the function is in a header file, you need to declare it inline, unless it's defined within a class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top