28

BruceEckelの「ThinkinginC++」から名前空間について読んでいるときに、次のステートメントに遭遇しました。

ただし、ヘッダーファイルにusingディレクティブが表示されることはほとんどありません(少なくともスコープ外ではありません)。その理由は、ディレクティブを使用すると、その特定の名前空間の保護がなくなり、その効果は現在のコンパイル単位が終了するまで続くためです。usingディレクティブ(スコープ外)をヘッダーファイルに入れると、この「名前空間保護」の喪失が、このヘッダーを含むすべてのファイル内で発生することを意味します。これは、多くの場合、他のヘッダーファイルを意味します。

上記の説明を簡単な例で理解するのを手伝っていただけませんか。

4

4 に答える 4

34

このプログラムを検討してください。

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です。

ここで、プログラムの上部を取り、1行目から5行目までをstruct string...までと、それをヘッダーファイルに入れて、その#include前に配置するとしますmain()。何も変わりません。まだエラーがあります。したがって、スタンドアロンプ​​ログラムの場合と同様に、usingステートメントを含むヘッダーファイルは、それらを含む他のコードで問題を引き起こし、ステートメントの一部をあいまいにする可能性があります。

ただし、ヘッダーは、直接または間接的に、任意に大量の依存コードによって含めることができるため、より大きな問題になる可能性があります。

  • usingヘッダーからステートメントを削除する、または
  • の内容の変更<string>、または影響を与えるその他のヘッダーstd::

...問題のあるヘッダーを含むコードを壊す可能性があります。どちらの問題も依存コードをコンパイルできなくする可能性があり、別のコンパイルが試行されるまで問題に気付かない可能性があります。さらに、ステートメントが原因で苦しんでいる人は、ヘッダーからステートメントを削除したり、影響を受けた他のクライアントコードを修正usingしたりするためのファイルシステム/コードリポジトリの権限、企業権限などを持っていない可能性があります。using

とはいえ、ヘッダーがクラスまたは関数内でのみ「使用」している場合、そのスコープを超えるコードには影響がないため、std::への変更による潜在的な影響は大幅に減少します。

于 2011-02-02T09:12:02.527 に答える
17

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

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

于 2011-02-02T08:54:30.933 に答える
6

「C++入門書、第5版」から次の段落をコピーします。

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

于 2013-06-22T18:44:37.427 に答える
4

さて、名前空間を使用することのポイントは何ですか。名前の衝突のリスクを回避するためです。

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

次にヘッダーを配置するusing A;using B;、A::FooBarとB::FooBarがFooBarだけに移動し、衝突が元に戻り、最初に名前空間を使用することによるメリットがなくなります。

于 2011-02-02T09:00:50.820 に答える