名前の競合を避けるために、C++ ライブラリは名前空間を使用する必要があることは理解していますが、既に次のことを行う必要があるためです。
#include
正しいヘッダー (または、使用するクラスを前方宣言します)- これらのクラスを名前で使用する
これら 2 つのパラメーターは、名前空間によって伝達される同じ情報を推測しないでください。名前空間を使用すると、3 番目のパラメーター (完全修飾名) が導入されるようになりました。ライブラリの実装が変更された場合、変更が必要になる可能性があることが3 つあります。これは、定義上、ライブラリ コードと私のコードとの間の結合の増加ではありませんか?
たとえば、Xerces-C を見てください。Parser
名前空間内で呼び出される純粋仮想インターフェイスを定義しますXERCES_CPP_NAMESPACE
。Parser
適切なヘッダー ファイルをインクルードし、名前空間をインポートするか、宣言using namespace XERCES_CPP_NAMESPACE
/定義の前にXERCES_CPP_NAMESPACE::
.
コードが進化するにつれて、別のパーサーを優先して Xerces を削除する必要があるかもしれません。私は、純粋仮想インターフェースによるライブラリ実装の変更から部分的に「保護」されています (ファクトリを使用してパーサーを構築する場合はなおさらです) が、Xerces から別のものに切り替えるとすぐに、次のことを行う必要があります。私のコードをくまなく調べて、すべての私のコードとコードを変更してusing namespace XERCES_CPP_NAMESPACE
くださいXERCES_CPP_NAMESPACE::Parser
。
最近、既存の便利な機能をライブラリに分割するために既存の C++ プロジェクトをリファクタリングしたときに、これに遭遇しました。
foo.h
class Useful; // Forward Declaration
class Foo
{
public:
Foo(const Useful& u);
...snip...
}
foo.cpp
#include "foo.h"
#include "useful.h" // Useful Library
Foo::Foo(const Useful& u)
{
... snip ...
}
当時、ほとんど無知 (そして部分的に怠惰) が原因で、 のすべての機能はuseful.lib
グローバル名前空間に配置されていました。
の内容が大きくなるuseful.lib
につれて (そしてより多くのクライアントがこの機能を使用し始めた)、 からすべてのコードをuseful.lib
と呼ばれる独自の名前空間に移動することが決定されました"useful"
。
クライアント.cpp
ファイルは簡単に修正できますusing namespace useful
。
foo.cpp
#include "foo.h"
#include "useful.h" // Useful Library
using namespace useful;
Foo::Foo(const Useful& u)
{
... snip ...
}
しかし、.h
ファイルは本当に労働集約的でした。using namespace useful;
ヘッダー ファイルを挿入してグローバル名前空間を汚染する代わりに、既存の前方宣言を名前空間にラップしました。
foo.h
namespace useful {
class Useful; // Forward Declaration
}
class Foo
{
public:
Foo(const useful::Useful& u);
...snip...
}
数十 (そして数十) のファイルがあり、これは大きな苦痛でした! それほど難しいことではなかったはずです。明らかに、設計および/または実装のいずれかで何か間違ったことをしました。
ライブラリ コードが独自の名前空間にある必要があることはわかっていますが、ライブラリ コードがグローバル名前空間にとどまり、代わりに#includes
?