0

I'm working with Code::Blocks. When I create a header-file foo.h and put forward-declarations as well as implementation into it, compilation works fine. Creating a foo.cpp file and putting nothing into it still works. But when I include the header-file within the implementation file, but keep the implementation in the header-file, I get an error about multiple declarations.

Example from my current Project

// header-file `GKit/math/blendprocs.cpp`
#include "GKit/utils/Color.h"

#ifndef _GKIT_MATH_BLENDPROCS_H_
#define _GKIT_MATH_BLENDPROCS_H_

    namespace GKit {
        namespace math {

            void blendAoverB(GKIT_COLORBLENDPROC_ARGSX) {
                D.a = A.a + (1 - A.a) * B.a;
                D.r = (A.a * A.r + (1 - A.a) * B.a * B.r) / D.a;
                D.g = (A.a * A.g + (1 - A.a) * B.a * B.g) / D.a;
                D.b = (A.a * A.b + (1 - A.a) * B.a * B.b) / D.a;
                GKIT_UTILS_COLOR_NORMALIZE(D);
            }

        }
    }

#endif // _GKIT_MATH_BLENDPROCS_H_

// implementation-file `GKit/math/blendprocs.cpp`
#include "GKit/math/blendprocs.h"

// Compilation output
-------------- Build: Debug in GKit ---------------

Compiling: GKit\math\blendprocs.cpp
Linking console executable: bin_debug\GKit.exe
build_debug\GKit\math\blendprocs.o:C:\Users\niklas\Desktop\GKit/./GKit/math/blendprocs.h:10: multiple definition of `GKit::math::blendAoverB(GKit::utils::Color const&, GKit::utils::Color const&, GKit::utils::Color&)'
build_debug\main.o:C:\Users\niklas\Desktop\GKit/./GKit/math/blendprocs.h:10: first defined here
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
2 errors, 0 warnings

Can you please help me understanding this error?

Niklas R
  • 16,299
  • 28
  • 108
  • 203

4 Answers4

1

In your header-file you would typically only put:

// header-file `GKit/math/blendprocs.cpp`
#ifndef _GKIT_MATH_BLENDPROCS_H_
#define _GKIT_MATH_BLENDPROCS_H_

#include "GKit/utils/Color.h"

namespace GKit {
    namespace math {

        void blendAoverB(GKIT_COLORBLENDPROC_ARGSX);

    }
}

#endif // _GKIT_MATH_BLENDPROCS_H_

And then in your CPP-file you put the actual implementation:

// implementation-file `GKit/math/blendprocs.cpp`
#include "GKit/math/blendprocs.h"

namespace GKit {
    namespace math {

        void blendAoverB(GKIT_COLORBLENDPROC_ARGSX) {
            D.a = A.a + (1 - A.a) * B.a;
            D.r = (A.a * A.r + (1 - A.a) * B.a * B.r) / D.a;
            D.g = (A.a * A.g + (1 - A.a) * B.a * B.g) / D.a;
            D.b = (A.a * A.b + (1 - A.a) * B.a * B.b) / D.a;
            GKIT_UTILS_COLOR_NORMALIZE(D);
        }

    }
}

Otherwise the implementation of your function will end up in all CPP-files that includes the header, which will confuse the linker when it tries to resolve the address of blendAoverB since it can find it in all object-files whose corresponding CPP-file included the header-file with the implementation.

On a side-note, it's better to put the include-guards (the #ifndef _GKIT_MATH_BLENDPROCS_H_ before anything else in your header-file (except maybe for comments).

Andreas Magnusson
  • 7,321
  • 3
  • 31
  • 36
1

You have a definition in a header. That definition will be duplicated in any source file that includes that header; since it's usually an error to have more than one definition in a program, the build fails. This is known as the One Definition Rule, sometime cryptically referred to as ODR.

The two best options are either:

  • Move the definition into a source file, leaving just a declaration in the header, or
  • Add inline to the definition; this relaxes the rule and allows multiple definitions in a program, as long as they are all identical.

Also, you shouldn't use reserved names for your include guards; you should remove the initial _ from _GKIT_MATH_BLENDPROCS_H_; and it's better to put those guards right at the start of the header, before any #include directives.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

You should either inline your implementation or put the implementation in the cpp file, not both.

// header "GKit/math/blendprocs.h"
#pragma once

#include "GKit/utils/Color.h"

namespace GKit {
        namespace math {
            void blendAoverB(GKIT_COLORBLENDPROC_ARGSX);
        }
    }

// implementation "GKit/math/blendprocs.cpp"
#include "GKit/math/blendprocs.h"

namespace GKit {
        namespace math {

            void blendAoverB(GKIT_COLORBLENDPROC_ARGSX) {
                D.a = A.a + (1 - A.a) * B.a;
                D.r = (A.a * A.r + (1 - A.a) * B.a * B.r) / D.a;
                D.g = (A.a * A.g + (1 - A.a) * B.a * B.g) / D.a;
                D.b = (A.a * A.b + (1 - A.a) * B.a * B.b) / D.a;
                GKIT_UTILS_COLOR_NORMALIZE(D);
            }

        }
    }

Or alternately inline it properly in the header using the inline keyword.

// header "GKit/math/blendprocs.h"
#pragma once

#include "GKit/utils/Color.h"

    namespace GKit {
        namespace math {
            inline void blendAoverB(GKIT_COLORBLENDPROC_ARGSX) {
                D.a = A.a + (1 - A.a) * B.a;
                D.r = (A.a * A.r + (1 - A.a) * B.a * B.r) / D.a;
                D.g = (A.a * A.g + (1 - A.a) * B.a * B.g) / D.a;
                D.b = (A.a * A.b + (1 - A.a) * B.a * B.b) / D.a;
                GKIT_UTILS_COLOR_NORMALIZE(D);
            }
        }
    }
AJG85
  • 15,849
  • 13
  • 42
  • 50
0

This is exactly what messages said. You should get familiar with Inline and ODR. You cant have multiple definition it is against ODR. I Guess your blendprocs.cpp is included more than once in different compilation units. it is related to Why aren't my compile guards preventing multiple definition inclusions?

ODR:

http://en.wikipedia.org/wiki/One_Definition_Rule

Community
  • 1
  • 1
CyberGuy
  • 2,783
  • 1
  • 21
  • 31