2012-02-14 5 views
1

問題を遭遇しましたが、回避することができましたが、なぜ機能していないのか分かりません。フレンドオペレータのオーバーロードによりリンカエラーが既に定義されています

これは私が使用しようとしたコードです。フィールドは簡潔にするためには削除されています。それらが必要している場合、私に教えてください、私はそれらを戻すだろう:

#pragma once 
#ifndef __PageStyle__ 
#define __PageStyle__ 
class PageStyle 
{ 
public: 
    friend bool operator<(const PageStyle& lhs, const PageStyle& rhs); 
}; 

bool operator<(const PageStyle& lhs, const PageStyle& rhs) 
{ 
    return (lhs.name < rhs.name); 
} 
#endif 

そして、私のソースファイルで、私はこのような何か:

#include "PageStyle.h" 

... 
void PageStyleManager::loadPageStyles() { 
    std::set<PageStyle> pageStyles; 
    ... 
} 

罰金コンパイルされたコードが、リンカスパッツをこのうち:

1>PageStyleManager.obj : error LNK2005: "bool __cdecl operator<(class PageStyle const &,class PageStyle const &)" ([email protected][email protected]@[email protected]) already defined in BaseContentFiller.obj 

BaseContentFillerはPageStyleManagerのためだけでなく、また、同様の方法でPageStyleを使用する他のクラスの基本クラスです。

もう少し掘り下げてから、私の目的(STLセットのクラスを使って)には、結局、非メンバーフレンドバージョンは必要ないことがわかりました。 私は、オペレータにインラインのパブリックメンバーと問題なくリンクされたコードをにしました。

なぜこの問題が発生しましたか?私はヘッダーガードを使用したことを保証しました。これはオペレータのオーバーロードに関する私の最初の実際の経験であり、私が間違ったことを知りたいと思います。

+1

非メンバ関数の*実装*は、静的でない限り、ヘッダーファイルに置かないでください。 –

+2

関連のない2つの問題: '#pragma once'は普遍的には理解されておらず、インクルードガードがいくつかの代替技術の動作を妨げる可能性があります。 '#pragma once'を使う場合は、インクルードガードの後ろに置いてください。シンボル内の二重のアンダースコアは、シンボルがインクルードガードであっても未定義の動作です。 –

答えて

9

ヘッダーファイルに関数の定義を含めると、ヘッダーファイルが含まれているTranslation unitに定義されます。
これはOne Definition Ruleに違反し、したがってリンカーのエラーです。

ヘッダーガードまたは#pragma onceは、同じヘッダーファイルが同じソースファイルに複数回含まれることを防ぎますが、別のTUで定義することはできません。

  1. ちょうど一つだけcppファイルのヘッダファイルで宣言と定義を追加したり、
  2. inlineとしてヘッダに定義された関数を作る:

    2つの溶液は、問題を解決することが可能です。

+0

cppファイルへの宣言を動かしました!私は様々なオンラインチュートリアルをちょっとしたものにしました(彼らはしばしばヘッダーとソースをインラインで表示しました)。振り返ってみると、ソースファイル内の演算子を宣言することは理にかなっています。 – seanhodges

6

ヘッダーファイルにoperator<を定義しないでください。そこに宣言し、ファイル.cppで定義してください。 #pragma onceは、同じ.cppファイルに複数回ヘッダーファイルが含まれないようにしますが、異なる.cppファイルに含まれる可能性があります。この場合、リンカーにはoperator<という複数の定義が表示されます。

+0

この回答は役に立ちました、ありがとう、Aasmund。私は追加のリソースへのリンクのためだけにもう1つを選択しました。 – seanhodges

+0

あなたの答えをマークするのではなく、私はまだあなたの10k担当者を得るためにupvotedしました:) – seanhodges

+0

@seanhodges:どういうわけか、私はそれが非常に満足できると思う...: –

関連する問題