web-dev-qa-db-ja.com

iostreamと名前空間stdの関係は何ですか?

私は現在、Teach Yourself C++ in 21 Days、Second Editionブックを使用して、Microsoft Visual C++ 2010 ExpressとともにC++コーディングについて学習しています。第1章の最後に、次のコードの記述とコンパイルに関する小さな演習があります。

#include <iostream>

int main ()
{
    cout << "Hello World!\n";
    return 0;
}

かなりシンプルですよね?しかし、驚いたことに、このエラーのためにコードはコンパイルされませんでした:

エラーC2065: 'cout':宣言されていない識別子

私はWebを精査し始め、すぐにいくつかの解決策を見つけました here 。コードにusing namespace std;を追加する必要がありました!

しかし、本には名前空間についての言及がなかったため、この本は古くなっていると思いました。 (これは#include <iostream.h>プリプロセッサディレクティブを使用します!)Web調査の結果、namespace std<iostream.h>に関するいくつかの歴史的背景とともに、名前空間<iostream>に関する多くの情報が見つかりました。この新しい情報の流れはすべて私を混乱させます。 (言うまでもなく、医療の性感染症に関するすべての不必要なGoogleの結果...)

だからここに私がこれまでに得たいくつかの質問があります:

  1. iostreamライブラリを含める場合、namespaceを検索するためにcoutが必要なのはなぜですか?名前の衝突を引き起こす可能性のある別のcoutがどこかにありますか?誰かがこれについて図を提供できれば、それは素晴らしいことです。

そしておまけとして、いくつかの歴史的背景:

  1. iostreamに変更される前のiostream.hは正確には何でしたか?

  2. namespaceはこの変更に関与しましたか?

22
IDDQD

すべての標準ライブラリ定義は、名前空間std内にあります。つまり、それらはグローバルスコープで定義されていないため、これらを使用するには、次のいずれかの方法でそれらを修飾する必要があります。

  • std::cout
  • using namespace std
  • using std::cout

たとえば、これを取ることができます:

// declarations
int global_variable;

namespace n {
int variable2;
}

global_variableはそのままアクセスできます。

int x;
x = global_variable;

ただし、variable2はグローバルスペースの一部ではなく、namespace nの一部です。

int x;
x = variable2; // error variable2 identifier not found.

したがって、完全修飾名を使用する必要があります。

int x;
x = n::variable2;

ショートカットとして次のように書くことができます:

using namespace n;
int x;
x = variable2; // variable2 is searched in current namespace
               // and in all namespaces brought in with using namespace
               // Found ONLY in namespace n -> OK

または

using n::variable2; // this makes any unqualified reference to `variable2`
                    // to be resolved to `n::variable2`
int x;
x = variable2;

ヘッダーファイルについては、標準が存在する前はiostream.hが多くのコンパイラで使用されていました。委員会は標準化を試みたとき、既存のコードとの互換性を壊さないためにC++ヘッダーを拡張しないことを決定しました。

20
bolov

この行は#で始まるため、「プリプロセッサディレクティブ」と呼ばれます。プリプロセッサは、コンパイルされる前にプログラムを読み取り、#で始まる行のみを実行します。プリプロセッサは、コンパイラのソースコードを設定します。

#includeディレクティブにより、プリプロセッサーは別のファイルの内容をプログラムに組み込みます。 iostreamファイルには、C++プログラムが画面に出力を表示し、キーボードから入力を取得できるようにするコードが含まれています。 iostreamファイルは、#includeディレクティブが出現した時点でプログラムに含まれています。 iostreamはヘッダーファイルと呼ばれ、プログラムの先頭または先頭に表示されます。

using namespace std;

C++は名前空間を使用して、名前またはプログラムエンティティを編成します。これは、プログラムが「std」と呼ばれるnamespaceの一部であるエンティティを評価することを宣言します。 iostreamファイルによって作成されたすべての名前は、そのnamespaceの一部です。

7
Jaythaceo

1。iostreamライブラリを含める場合、namespaceを検索するためにcoutが必要なのはなぜですか?どこかに別のcoutがありますか?名前の衝突を引き起こしますか?

C++標準では、coutstdネームスペース内にあることが要求されているため、これが必要です。ありますcould衝突するcoutがありますが、標準ライブラリ(たとえば、独自のコードやサードパーティのライブラリ)にはありません。

1。正確にはiostream.hに変更される前iostream

これは標準の一部ではないため、何でもかまいませんが、iostreamの基礎となった事前標準化ヘッダーの名前でした。通常、それはグローバル名前空間のすべての名前を宣言したので、あなたが見ている例は事前標準化で書かれたと思われます。

2 ._namespaceはこの変更に関与しましたか?

この質問は不明確です。キーワードnamespaceは実装内で使用でき、データ、関数、型などを名前空間内で宣言および定義するために使用されます。したがって、この変更にはsomeの部分がありました。

namespace foo
{
  void bar();  // declares foo::bar
}
3
juanchopanza

C++では、識別子を論理的に namespaces にグループ化できます。 coutストリームは名前空間std内にあります。 3通りの使い方ができます。

  1. 書く using namespace stdを先頭にして、以前と同じようにcoutを使用します。
  2. 書く using std::coutを先頭にして、以前と同じようにcoutを使用します。
  3. 使用する std::coutの代わりにcout
1
Mohit Jain

@bolov ..これを参照してポイントを理解する standard のおかげで、これは宣言です。

#include <ios>
#include <streambuf>
#include <istream>
#include <ostream>

namespace std 
{
    extern istream cin;
    extern ostream cout;
    extern ostream cerr;
    extern ostream clog;

    extern wistream wcin;
    extern wostream wcout;
    extern wostream wcerr;
    extern wostream wclog;
}

0
norrr