0

私はCode::Blocksを使用しています。ヘッダーファイルを作成し、foo.h前方宣言と実装をそのファイルに入れると、コンパイルは正常に機能します。ファイルを作成しfoo.cppて何も入れない場合でも機能します。しかし、実装ファイル内にヘッダーファイルをインクルードし、実装をヘッダーファイル内に保持すると、に関するエラーが発生しますmultiple declarations

私の現在のプロジェクトからの例

// 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

このエラーを理解するのを手伝ってもらえますか?

4

4 に答える 4

1

ヘッダーファイルには、通常、次のものだけを入れます。

// 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_

次に、CPPファイルに実際の実装を配置します。

// 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);
        }

    }
}

blendAoverBそうしないと、関数の実装がヘッダーを含むすべてのCPPファイルになり、対応するCPPファイルにヘッダーが含まれているすべてのオブジェクトファイルでリンカーがアドレスを見つけられるため、リンカーがアドレスを解決しようとすると混乱します。 -実装を含むファイル。

ちなみに、インクルードガード(#ifndef _GKIT_MATH_BLENDPROCS_H_ヘッダーファイルの何よりも前に(コメントを除く)を配置することをお勧めします。

于 2012-04-18T19:15:57.000 に答える
1

ヘッダーに定義があります。その定義は、そのヘッダーを含むすべてのソースファイルに複製されます。通常、プログラムに複数の定義があるとエラーになるため、ビルドは失敗します。これは、単一定義規則と呼ばれ、不可解にODRと呼ばれることもあります。

2つの最良のオプションは次のいずれかです。

  • 定義をソースファイルに移動し、ヘッダーに宣言だけを残すか、または
  • inline定義に追加します。これにより、ルールが緩和され、すべてが同一である限り、プログラム内で複数の定義が可能になります。

また、インクルードガードに予約名を使用しないでください。;_からイニシャルを削除する必要があります。_GKIT_MATH_BLENDPROCS_H_そして、それらのガードをヘッダーの先頭、#includeディレクティブの前に配置することをお勧めします。

于 2012-04-18T19:16:27.273 に答える
1

実装をインライン化するか、実装をcppファイルに入れる必要があります。両方ではありません。

// 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);
            }

        }
    }

または、inlineキーワードを使用してヘッダーに適切にインライン化します。

// 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);
            }
        }
    }
于 2012-04-18T19:16:29.477 に答える
0

これはまさにメッセージが言ったことです。インラインとODRに精通している必要があります。ODRに反する複数の定義を持つことはできません。私はあなたのblendprocs.cppが異なるコンパイルユニットに複数回含まれていると思います。これは、コンパイルガードが複数の定義の包含を防止しないのはなぜですか?に関連しています。

ODR:

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

于 2012-04-18T19:16:33.967 に答える