ライブラリの名前衝突回避について
自作ゲームの開発で最近嵌ったことのメモ書きです。
以下のようなポリゴンクラスを作り、WinAPIとともに併用したプログラムを書いたときに起こったエラーです。
class Polygon : virtual public Texturable { public: Polygon(); virtual Polygon(); boost::shared_ptr<Vertex> GetVertex(); void Draw(); };
Polygon pol;
何の変哲もないコードですが、上記をコンパイルすると大量のエラーが発生します。
Polygonが定義されていないというエラーです。
しかし、実際にはPolygonクラスを定義しています。
これは、WinAPIでPolygonという名前の関数が既に宣言されていたためです。
既に宣言されている関数名を用いてクラスを作成しようとしていたため、結果として名前衝突が起こっていました。
このように、思わぬこところで名前衝突の問題に悩まされるケースも少なくありません。
このような問題を解決する方法としては、独自の名前空間で定義する、プレフィックスを付けるといったものがあります。
一般にC++のライブラリはこのどちらかの方法を用いていることがほとんどです。
他のライブラリとの名前衝突を避けるためだと思われます。
上記ポリゴンクラスは、名前空間内で定義すれば解決できます。
namespace MyArea { class Polygon : virtual public Texturable { public: Polygon(); virtual Polygon(); boost::shared_ptr<Vertex> GetVertex(); void Draw(); }; }
MyArea::Polygon pol;
ところが、上記では解決しないパターンも存在します。
class WinWindowFactory : public WindowFactory { public: WinWindowFactory(); virtual ~WinWindowFactory(); boost::shared_ptr<window> CreateWindow(); };
WinWindowFactory factory; Window win = factory.CreateWindow()
上記も何の変哲もないコードですが、ビルドすると失敗します。
これは、WinAPI側でCreateWindowマクロが定義されているためです。
このような問題には#undefでマクロ定義を打ち消す方法があります。
// 名前が衝突するマクロ定義を除外 #ifdef CreateWindow #undef CreateWindow #endif // CreateWindow class WinWindowFactory : public WindowFactory { public: WinWindowFactory(); virtual ~WinWindowFactory(); boost::shared_ptr<window> CreateWindow(); };
WinWindowFactory factory; Window win = factory.CreateWindow()
これでビルドが成功します。
2つ目の問題は少々厄介ですが、マクロをによる名前衝突の場合は上記のような対処をすればよいかと思います。