2

同僚と口論になりました。

名前空間のメンバーであるクラスがあります(これは他の名前空間のメンバーですが、ここでは重要ではないと思います)。ヘッダー ファイルでは、次のようにクラス ブロックを名前空間ブロックに入れ子にします。

namespace NS {
    class A {
        void method();
        // ...
    };
}

そして、これが .cpp ファイルであり、私たちの議論の主題です。私が書いた:

using namespace NS;

void A::method() {
    // ...
}

同僚は、私が「using」ディレクティブを不適切に使用していて、ここでヘッダーと同じ NS { ... } を使用するべきだったと私に言いました。(彼はコードを変更し、いくつかのコンパイラ エラーを取得しましたが、using ディレクティブを削除し、コードを NS { ... } で囲むことによってのみ取り除くことができました。)

私の要点は、「using」は名前の検索に影響するだけなので、NS名前空間でAが検索されるため、私のアプローチは正しいです。彼のコンパイラの問題は、その「using」ディレクティブではなく、他の何かによって引き起こされました。

誰が正しいのか、その理由は?

追加:皆さん、「私はこれ (またはあれ) を何度もやった」などと答えないでください。あまり役に立ちません。ここで理論が必要です。これまたはそのアプローチがなぜ正しいか、または間違っているかです。

4

6 に答える 6

4

あなたの同僚は正しいです.cppをnamesapceでラップする必要があります.namesapce NS内で関数を定義することを意味します.

namespace NS
{    
  void A::method() 
  {
    // ...
  }
}

複数の A が利用可能な場合、競合名のルックアップが発生する可能性があります。

ここで起こっている危険なことは、using 宣言がA::method、using 宣言に遭遇するまでに名前空間 NS で名前が付けられたエンティティのスナップショットを取得することです。

名前空間に関するGoogle cpp スタイル ギルド、および101 の c++ コーディング標準を読んでください。

于 2013-01-31T02:34:19.760 に答える
3

どちらもさまざまな点で正しいです。using ディレクティブを使用すると、コンパイラがAinvoid A::method()を beNS::Aに解決できるという点であなたは正しいですが、ほとんどの場合、名前空間を開いた方がよいという点でも彼は正しいです。

その理由は、ヘッダーの名前空間で宣言されているすべてが検索されるわけではなく、それらの要素については名前空間を開く (または手動で修飾を提供する) 必要があるため、統一されたアプローチを提供することは理にかなっています。

一般的な例は、型に適用される演算子の定義です。

// header
namespace NS {
   class A { ... };
   std::ostream& operator<<(std::ostream&,A const&);
}
// implementation file (incorrect):
using namespace NS;
std::ostream& operator<<(std::ostream& o, A const & a) {
   // do something
}

ここでの問題は、関数定義 (関数名が修飾名でない場合) が自己宣言であることです。ヘッダーでは、演算子は として宣言されて::NS::operator<<いますが、実装ファイルでは として定義されていstd::ostream& ::operator<<(std::ostream&, NS::A const&)ます。using ディレクティブを使用すると、A識別子を に解決できますが、その関数定義が名前空間NS::Aに存在することはありません。NS

これは微妙な問題につながります::NS::operator<<.ADLが原因でその演算子を使用すると検出されますが、その演算子はどこにも定義されていません(ただし、別の名前空間に同様の演算子があります)。

そうは言っても、すべての型の名前空間を必要とし、自由な関数定義は名前空間ので実行し、自己宣言を避けるために常に修飾する必要があるコーディング規則がいくつかあります (私が現在働いている場所にはそのようなガイドラインがあります)。上記の例では、演算子は実装ファイルで次のように定義されます。

std::ostream& ::NS::operator<<(std::ostream& o, A const& a) { ... }

ただし、常に修飾することに本当に慣れていない限り、関数の修飾を忘れるとエラーが発生しやすくなります。

于 2013-01-31T02:41:20.253 に答える
1
namespace NS {
    class A {
        void method();
        // ...
    };
}

いつもそうやってたのに…

于 2013-01-31T02:34:24.540 に答える
0

あなたは正しいです。using私はこれに何度も悩まされてきました (つまり、宣言はこれを行わないと考えて噛まれました)。これを書くには 3 つの方法があり、すべてうまくいきます。

namespace NS
{
    void A::method()
    { }
}

または:

NS::A::method() { }

または:

using namespace NS;

A::method() { }

ただし、スタイルに関しては、1 番目または 2 番目のいずれかをお勧めしますusing。同じ名前とメソッドを持つ複数のクラスがあると、宣言が複雑になる可能性があります。

于 2013-01-31T02:36:24.457 に答える
0

コード宣言またはライブラリで「名前空間を使用する」を使用しないことをお勧めしますが、実際のプログラムのコードに使用しても問題ありません。

つまり、Cpp 定義には使用しないでください。ただし、外部で関数/クラスを呼び出すときに使用できます。

これはすべて優れたコーディング手法であり、他の人があなたのコードを使用していない限り、あなたが何を望むかが重要です。

読みやすくするために、cpp コードを Namespace { ... } に入れるのが最善です。

于 2013-01-31T02:38:13.963 に答える