タイルベースのゲーム (正方形、線など) でタイルのさまざまな形状を描画するのに役立つテンプレート関数のコレクションを含む、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"); }
したがって、技術的には、すべての関数の前にテンプレート宣言を配置することもできますが、それでは地獄に落ちることは間違いありません。何が起こっているのか分かりますか?