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


88

インターフェイス宣言ファイル(*.hまたは*.hpp)とその実装ファイル(*.cpp)の2つのソースファイルのペアについて考えてみます。

ましょ*.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つのプラクティスの間に違いはあり、一方が他方よりも優れていると見なされますか?


30
オプション3もありますint MyNamespace::MyClass::foo() ...。たとえば、フルネームだけを使用してください。
ベンジャミンバニエ2012年


@Daveは重複していません。これらの質問は互いに補完し合っています。この質問に、Daveから提供されたリンクを「Readalso ...」として追加することをお勧めします。私の質問は、初心者が正しいスタイルを選択するのに役立ちます。
nickolay 2012年

回答:


62

コードの可読性の観点から、私の意見では、この理由で#2の方法を使用する方がおそらく良いでしょう。

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


デイブがあなたの質問に彼のコメントでリンクした質問はまた、あなたが見ている2つの方法の違い(もしあれば)のいくつかの重要なポイントを概説しています
ダンF

みんな、私は本当に誰の答えを選ぶべきかわかりません。それらは互いに補完しながら交差点を持っています。
nickolay 2012年

CLionのような一部のIDEは、オプション/プラクティス#2を使用した場合にのみ実装を検出することを認めるためにコメントするだけです。
PedroTanaka 2015

@PedroTanakaこれはまだ当てはまりますか?私はそのような問題に気づいていません。
ジョンマクファーレーン2016年

@JMcFコメントを公開してからチェックしていません。Clionの初期バージョンでは、問題が発生しました。
PedroTanaka 2016年

51

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

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

また、非常に冗長です。ほとんどの人にとってはあまりにも多すぎます。以来using namespace、私の経験では、少なくとも名前の競合のためrecepeが、あり、そして非常に限られたスコープと場所を除いて避けるべきである、私は一般的にあなたの#2を使用します。


3
非常に明確に感謝します。一緒に、名前空間ユーザー向けの優れたFAQページを作成しました。:)
nickolay 2012年

2
みんな、私は本当に誰の答えを選ぶべきかわかりません。それらは互いに補完しながら交差点を持っています。
nickolay 2012年

10

これら2つのプラクティスの間に違いはありますか

はい。#1と#2は、それぞれusingディレクティブ名前空間定義の例です。この場合、これらは事実上同じですが、他の結果があります。たとえば、と一緒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に代わる可能性のある方法は、関心のある識別子のみを含むusing宣言です。

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

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

4

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


0

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

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

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

これにより、クラスに多くの関数がある場合に、名前空間名を何度も入力する手間が省けます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.