1

タイルベースのゲーム (正方形、線など) でタイルのさまざまな形状を描画するのに役立つテンプレート関数のコレクションを含む、ShapeBuilder という名前の C++ 名前空間があります。この名前空間のすべての関数は、非テンプレート関数を作成しようとするまで、エラーなしでテンプレートを使用しました-次のような単純なもの

void hey() { printf("Hey"); }

次のエラーが発生しました。

1>HouseGenerator.obj : error LNK2005: "void __cdecl ShapeBuilder::hey(void)" (?hey@ShapeBuilder@@YAXXZ) already defined in Game.obj
1>WorldBuilder.obj : error LNK2005: "void __cdecl ShapeBuilder::hey(void)" (?hey@ShapeBuilder@@YAXXZ) already defined in Game.obj
  • WorldBuilder は名前空間 ShapeBuilder を使用します (もちろん、ShapeBuilder.h も含まれます)。
  • HouseGenerator は WorldBuilder のフレンド クラスで、WorldBuilder.h を含みます。
  • すべての ShapeBuilder コードは、WorldBuilder.h を含む ShapeBuilder.h に記述されています。
  • 再帰的包含を防ぐために、関連するすべてのクラスで #pragma once を実際に使用しました。

トップ コードを次のコードに置き換えると、エラーが解消されます。

template <class T>
void hey() { printf("Hey"); }

したがって、技術的には、すべての関数の前にテンプレート宣言を配置することもできますが、それでは地獄に落ちることは間違いありません。何が起こっているのか分かりますか?

4

1 に答える 1

1

2 つのオプションがあります。

  1. 関数を に変更しますinline

    inline void hey() { printf("Hey"); }
    
  2. ヘッダー ファイルで関数を宣言しますが、定義はしません。.cc ファイルで定義します。

于 2014-05-08T16:36:06.303 に答える