2011-02-02 83 views
24

ブルースEckel氏の名前空間について、「C++で考える」から読みながら、私は次のステートメントが発生しました:あなたは、少なくともしない範囲の外にヘッダファイル (にディレクティブを使用して を見ない事実上決してしかしC++でヘッダーファイルに "using namespace"を使用するのはなぜですか?

は、 )。理由は の理由は、 ディレクティブを使用してその特定の名前空間 の保護を取り除き、最後に の効果が最後になるまでです。 コンパイル単位。あなたは ヘッダファイルに(範囲外)を使用して ディレクティブを入れた場合、それは 「名前空間の保護」のこの損失は 以内に、多くの場合、他のヘッダ のファイルを意味し、この ヘッダを含み、任意のファイルを発生することを意味します。

簡単な例で上記の説明を理解してもらえますか?

+3

Yeapは、ここに行く:http://stackoverflow.com/questions/2152925/can-i-undo-the-effect-of-using-namespace-in-c – sharptooth

+4

@sharptooth:「私にしてみましょうStackOverflowのそれはあなたのために」私の頭の中に飛び込んできました。 – Mehrdad

+0

@Mehrdad:LOL、私たちはその段階には到達しないことを願っています。 – sharptooth

答えて

25

このプログラムを考えてみましょう:

line# 
    1 #include <string>                
    2                     
    3 using namespace std;                
    4                     
    5 struct string { const char* p; }; // Beware: another string! 
    6                     
    7 int main()                  
    8 {                    
    9  string x; // Error: ambiguous - which string is wanted? 
    10 } 

あなたはそれをコンパイルしようとすると、エラーが表示されます:

g++  using.cc -o using 
using.cc: In function `int main()': 
using.cc:9: error: use of `string' is ambiguous 
using.cc:5: error: first declared as `struct string' here 
/usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stringfwd.h:60: error: 
    also declared as `typedef struct std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::string' here 
using.cc:9: error: `string' was not declared in this scope 
using.cc:9: error: expected `;' before "x" 

をここでの問題は、main()string x;を指定した場合、コンパイラはどうかわからないということですユーザー定義の::stringまたはstd::stringが必要です。までとstruct string含む...とmain()前にあなたがして#includeヘッダファイルに入れて -

は今ライン1〜5 ...あなたがプログラムの先頭部分を取ることを想像してみてください。変更はありません。まだエラーがあります。したがって、スタンドアロンプ​​ログラムの場合と同様に、ヘッダファイルにusing文が含まれると、それらを含む他のコードに問題が発生し、ステートメントの一部があいまいになる可能性があります。

ヘッダーは直接的または間接的に - 任意の巨大な依存コードによって含めることができますが、それはもっと大きな痛みになる可能性があります。ヘッダからusing文を削除

  • 、または
  • <string>の内容への変更、またはstd::

に影響を与える他のヘッダが...問題のヘッダを含むコードを壊すかもしれません。どちらの問題でも、依存するコードはコンパイル不可能になる可能性があり、別のコンパイルが試行されるまで問題が認識されないことさえあります。さらに、usingステートメントに苦しんでいる人は、ファイルシステム/コードリポジトリのアクセス許可、法人権限などを持たずにヘッダからusingステートメントを削除したり、他の影響を受けるクライアントコードを修正することはできません。

つまり、ヘッダーがクラスまたは関数内で "使用する"場合、そのスコープを超えたコードには影響がないため、std ::への変更による潜在的な影響が大幅に軽減されます。

+0

素敵な説明..本当にありがとうございます – user388338

+0

@ user388338:歓迎...歓声。 –

15

ヘッダーにusing namespace stdが含まれている場合、その名前空間のすべてがヘッダーを含むすべてのモジュールにグローバル名前空間に追加されます。

つまり、これらのモジュールのグローバル名前空間のstd関数/クラスと同じ名前(および関数の互換パラメータ)を持つクラスを決して宣言することはできません。

+0

ありがとうございました.. – user388338

+1

"関数を宣言したり、同じ名前のクラスを定義することはできません" - 実際には、呼び出し元が使用法を明確にしなければならないということだけで、グローバルバージョンは優先的に':: identifier'のようにアクセスする必要がありますが、' 'used ''バージョンは' :: std :: identifier'のようにアクセスする必要があります。興味深いことに、あいまいさがなければ、明示的な ':: identifier'は" used "バージョンを見つけるので、"あなたの "名前空間のすべてがグローバルに追加されます"というのは正しい考え方です。 '::'接頭辞なしの二次暗黙的な検索場所.... –

4

まあ、名前空間を使用するポイントは何ですか?名前の衝突の危険性を避けることです。

たとえば、かなり一般的なクラス名(FooBarなど)があるとします。複数のライブラリを使用すると、ライブラリAのFooBarがライブラリBのFooBarと衝突する危険性があります。そのために、FooBarsをグローバル名前空間からA :: FooBarおよびB :: FooBarに移動するために2つの異なる名前空間AおよびBを使用します(したがって、彼らはお互いに離れている)。

あなたがヘッダにusing A;using B;を置く場合、これはその後:: FooBarのとBを移動します:: FooBarのをただFooBarのに、衝突を戻す、最初の場所で名前空間を使用してからゲインを取り除きます。

4

コピー「C++入門、第五版」から次の段落は:ヘッダ内の

コードは通常using宣言を使用しないでください。 の理由は、ヘッダーの内容がプログラムのテキストを含む にコピーされるためです。ヘッダーに使用宣言がある場合は、そのヘッダーを含むすべてのプログラムが同じ宣言を使用して取得されます。 と指定されたライブラリ を使用しようとしなかったプログラムは、予期しない名前の競合が発生する可能性があります。

関連する問題