2

クラスとポインターについてさらに学習した後、私は持っていたプログラムをリファクタリングし、他の 2 つのクラスを作成する過程で 200 行を超えるコードを削除しましLocationPiece。問題は、すべてをコンパイルした後、リンカーがコンストラクターPieceが複数回定義されていると不平を言い、多くのエラーが発生することです。

In function 'Piece':                                         board.o
multiple definition of 'Piece::Piece(int)`                   char_traits.h
In function 'Piece':                                         board.o
multiple definition of 'Piece::Piece(int)`                   piece.cpp
In function 'Piece':                                         player.o
multiple definition of 'Piece::Piece(int)`                   piece.cpp
In function 'Piece':                                         player.o
multiple definition of 'Piece::Piece(int)`                   piece.cpp (yes, same exact error!)
In function 'Piece':                                         refereee.o
multiple definition of 'Piece::Piece(int)`                   char_traits.h
In function 'Piece':                                         referee.o
multiple definition of 'Piece::Piece(int)`                   piece.cpp
...

のエラーをクリックすると、次のchar_traits.hようになります。

static size_t
length(const char_type* __s) //error points here to line 262
{ return __builtin_strlen(__s); }

別の人char_traits.hが私を連れてきます

  static int
  compare(const char_type* __s1, const char_type* __s2, size_t __n) //line 258, error points here too
  { return __builtin_memcmp(__s1, __s2, __n); }

ご存知のとおり、location.h は piece.h をインクルードする唯一のものであり (他のファイルには、piece.h を含む場所から間接的に piece.h がインクルードされます)、board.h は location.h をインクルードする唯一のものです。クラスの束にはboard.hが含まれます

ヘッダー ガードを_OTHELLO_PIECE_Hに変更し、クラスの名前を (IDE 経由で) OPiece に変更しようとしました。どちらも問題を解決しませんでした。

面白いことに、エラーの 1 つに「in function 'OPiece':」があり、その後、chatter.ochatter.h にも chatter.cpp にも OPiece を含むものは何も含まれていないにもかかわらず、私の IDE は を置きます。

この再定義エラーの原因は何ですか?

4

5 に答える 5

4
  1. すべてを再構築する
  2. Piece::Piece を探し、ヘッダー ファイルからすべて削除します 2b. .cpp ファイルを #include しない
  3. Piece に解決される #define を探します
于 2010-10-29T17:34:39.513 に答える
2

複数の関数定義エラーの最も一般的な原因は、関数定義をヘッダー ファイルに入れ、それを作成するのを忘れていることinlineです。

あまり心配する必要はありませんchar_traits.h。これはおそらく、テンプレートの回り込みが原因で、リンカーがその特定のオブジェクト ファイルで定義が行われたと主張するためのより良い場所を見つけられなかったことを意味します。

于 2010-10-29T17:31:13.300 に答える
1

Piece::Piece(int)一般的なビルドで実装する場所は 2 つあります。

1) インターフェース (宣言時)

class Piece {
    int d_a;
public:
    Piece(int a) : d_a(a) {
    }
    /* ... */
};

2) 専用の cpp ファイルで

Piece.hppで

class Piece {
    int d_a;
public:
    Piece(int a);
    /* ... */
};

Piece.cppで

Piece::Piece(int a) : d_a(a) {
}

ただし、テンプレートの定義は異なります。

このエラーは、多くの場合Piece::Piece(int a) : d_a(a) {}、複数の cpp ファイルに含まれていることを示しています。

生成された各オブジェクト ファイルは、それが表示される場所にシンボルを追加しPiece::Piece(int)ます。

ビルドの最後に、すべてのオブジェクトがマージ/リンクされて、最終的なバイナリまたは実行可能ファイルが作成されます。次に、リンカーはこの定義のコピーがあることを認識し、エラーを生成します。

これを診断する簡単な方法の 1 つは (ビルドに時間がかからないことを前提としています):

#warning Piece::Piece(int) is visible here
Piece::Piece(int a) : d_a(a) {
}

正確に 1 つの警告が発行されます。さらに発行された場合、コンパイラーは少しの情報 (インクルード順序など) を提供する可能性があります。

于 2010-10-29T17:53:44.630 に答える
1

コンストラクターの実装は、 にpiece.cpp直接ではなく、 に配置する必要がありpiece.hます。

于 2010-10-29T17:32:07.660 に答える
0

単なる推測: 使ったの#includeか、それとも#import偶然使ったのか -- 私にも一度ありました :-)

于 2010-10-29T17:34:12.510 に答える