web-dev-qa-db-ja.com

C ++:名前空間-ヘッダーファイルとソースファイルで正しく使用する方法

インターフェース宣言ファイル(*.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つのプラクティス間に違いはありますか?

72
DaddyM

コードの読みやすさの観点からは、おそらくこの理由で2番目の方法を使用する方が良いと思います。

一度にusing複数の名前空間になることができ、その行の下に記述されたオブジェクトまたは関数は、これらの名前空間のいずれかに属することができます(名前の競合を除きます)。 namespaceブロックでファイル全体をラップすることはより明示的であり、.cppファイル内でその名前空間に属する新しい関数と変数を宣言することもできます。

54
Dan F

最も明確なのは、表示しなかったオプションです。

int MyNamespace::MyClass::foo()
{
    //  ...
}

また、非常に冗長です。ほとんどの人にとっては多すぎる。 using namespaceは、少なくとも私の経験では、名前の競合のレセプトであり、非常に限られた範囲と場所を除き、避けるべきです。私は通常、#2を使用します。

44
James Kanze

これらの2つの慣習に違いはありますか

はい。 #1と#2は、それぞれ sing-directivenamespace 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() { ... }
7
John McFarlane

また、何らかの理由で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番目の方法を適用するとこれで問題ありません。

4
Jordan

sing-declarationを使用して、もう1つの方法を追加したいと思います。

#include "MyClass.h"
using MyNamespace::MyClass;

int MyClass::foo() { ... }

この方法により、クラスに多くの関数がある場合、名前空間名を何度も入力する必要がなくなります。

0
Joanna