インターフェース宣言ファイル(*.h
または *.hpp
)とその実装ファイル(*.cpp
)。
*.h
ファイルは次のようになります。
namespace MyNamespace {
class MyClass {
public:
int foo();
};
}
ソースファイルで名前空間を使用するための2つの異なるプラクティスを見てきました。
*.cpp
プラクティス#1を示しています
#include "MyClass.h"
using namespace MyNamespace;
int MyClass::foo() { ... }
*.cpp
プラクティス#2を示す:
#include "MyClass.h"
namespace MyNamespace {
int MyClass::foo() { ... }
}
私の質問:これら2つのプラクティス間に違いはありますか?
コードの読みやすさの観点からは、おそらくこの理由で2番目の方法を使用する方が良いと思います。
一度にusing
複数の名前空間になることができ、その行の下に記述されたオブジェクトまたは関数は、これらの名前空間のいずれかに属することができます(名前の競合を除きます)。 namespace
ブロックでファイル全体をラップすることはより明示的であり、.cppファイル内でその名前空間に属する新しい関数と変数を宣言することもできます。
最も明確なのは、表示しなかったオプションです。
int MyNamespace::MyClass::foo()
{
// ...
}
また、非常に冗長です。ほとんどの人にとっては多すぎる。 using namespace
は、少なくとも私の経験では、名前の競合のレセプトであり、非常に限られた範囲と場所を除き、避けるべきです。私は通常、#2を使用します。
これらの2つの慣習に違いはありますか
はい。 #1と#2は、それぞれ sing-directive と namespace definition の例です。この場合、これらは事実上同じですが、他の結果があります。たとえば、MyClass::foo
と共に新しい識別子を導入する場合、スコープは異なります。
#1:
using namespace MyNamespace;
int x; // defines ::x
#2:
namespace MyNamespace {
int x; // defines MyNamespace::x
}
一方が他方より優れていると考えられていますか?
#1長所:もう少し簡潔。誤ってMyNamespace
に何かを誤って導入することは困難です。短所:既存の識別子を意図せずに取り込む可能性があります。
#2長所:既存の識別子の定義と新しい識別子の宣言の両方がMyNamespace
に属することをより明確にします。短所:意図せずにMyNamespace
に識別子を導入する方が簡単です。
#1と#2の両方の批判は、おそらくMyNamespace::MyClass
のメンバーの定義だけを気にしているとき、名前空間全体を参照しているということです。これは手間がかかり、意図を十分に伝えません。
#1の代替案として、 sing-declaration があります。これには、関心のある識別子のみが含まれます。
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
また、何らかの理由でcppファイルにテンプレートの特殊化を実装し、using namespace
次の問題が発生します。
// .h file
namespace someNameSpace
{
template<typename T>
class Demo
{
void foo();
};
}
// .cpp file
using namespace someNameSpace;
template<typename T>
void Demo<T>::foo(){}
// this will produce
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive]
template<>
void Demo<int>::foo(){}
それ以外の場合は、2番目の方法を適用するとこれで問題ありません。
sing-declarationを使用して、もう1つの方法を追加したいと思います。
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
この方法により、クラスに多くの関数がある場合、名前空間名を何度も入力する必要がなくなります。