включить и использовать пространство имен в C++

для использования cout мне нужно указать оба:

#include<iostream>

и

using namespace std;

Где определяется cout? в iostream, верно? Значит, само iostream находится в пространстве имен std?

В чем смысл обоих утверждений относительно использования cout?

Я смущен, почему мы должны включить их обоих.


person Moeb    schedule 15.04.2010    source источник
comment
@Neil Тогда в чем цель ТАК? Задавать только вопросы, на которые невозможно ответить, прочитав книгу или поискав в Интернете?   -  person Kevin Crowell    schedule 15.04.2010
comment
@Нил Баттерворт: хорошо! больше никаких глупых вопросов после этого, без прочтения концепций из книги.   -  person Moeb    schedule 15.04.2010
comment
@Kevin Любой, кто думает, что может выучить C ++, задавая вопросы по SO, вводит себя в заблуждение и тратит наше время впустую.   -  person    schedule 15.04.2010
comment
Я думаю, что вопрос подходит для SO. SO не предназначался для зарезервированных только для неясных/расширенных вопросов.   -  person Jeremy Friesner    schedule 15.04.2010


Ответы (4)


iostream — это имя файла, в котором определен cout. С другой стороны, std — это пространство имен, эквивалентное (в некотором смысле) пакету java.

cout — это экземпляр, определенный в файле iostream внутри пространства имен std.

Может существовать еще один экземпляр cout в другом пространстве имен. Таким образом, чтобы указать, что вы хотите использовать экземпляр cout из пространства имен std, вы должны написать

std::cout, указывающий область применения.

std::cout<<"Hello world"<<std::endl;

Чтобы избежать std:: везде, вы можете использовать предложение using.

cout<<"Hello world"<<endl;

Это две разные вещи. Один указывает область действия, другой — фактическое включение cout.

В ответ на ваш комментарий

Представьте, что в iostream существуют два экземпляра с именем cout в разных пространствах имен.

namespace std{
   ostream cout;
}
namespace other{
   float cout;//instance of another type.
}

После включения <iostream> вам все равно нужно указать пространство имен. Оператор #include не говорит: «Эй, используйте cout в std::. Вот для чего нужен using, чтобы указать область действия

person Tom    schedule 15.04.2010
comment
@Tom: Когда я уже включил файл (iostream), я указал, какое определение cout использовать. Теперь компилятор знает, какое определение использовать. Так в чем тогда проблема. Я все еще не понимаю, почему мне нужно сказать, что он находится в пространстве имен std. Это должно было быть необходимо, если возникла некоторая путаница. Здесь нет путаницы, так как существует только одно определение cout. - person Moeb; 15.04.2010
comment
@cambr: Нет, вы указали определение cout для использования. Нет никаких причин, по которым вы не могли бы определить int cout; впоследствии, хотя это и плохая идея. Возможно, стандарт C++ мог бы потребовать, чтобы пространства имен игнорировались, если есть только одно пространство имен с заданным символом, но этого не произошло, и я не могу придумать язык, использующий пространства имен, где это происходит. - person David Thornley; 15.04.2010

Если ваша реализация C++ использует файлы заголовков в стиле C (многие так и делают), то есть файл, который содержит что-то похожее на:

#include ... // bunches of other things included

namespace std {

... // various things

extern istream cin;
extern ostream cout;
extern ostream cerr;

... // various other things

}

std — это пространство имен, в котором стандарт C++ говорит, что большинство стандартных вещей должны находиться в нем. Это сделано для того, чтобы не допустить переполнения глобального пространства имен, что может затруднить придумывание имен для ваших собственных классов, переменных и функций, которые не т уже используются в качестве имен для стандартных вещей.

Говоря

using namespace std;

вы сообщаете компилятору, что хотите, чтобы он выполнял поиск в пространстве имен std в дополнение к глобальному пространству имен при поиске имен. Если компилятор видит исходную строку:

return foo();

где-то после строки using namespace std; он будет искать foo в разных пространствах имен (аналогично областям видимости), пока не найдет foo, удовлетворяющий требованиям этой строки. Он ищет пространства имен в определенном порядке. Сначала он просматривает локальную область (которая на самом деле является безымянным пространством имен), затем следующую, самую локальную область видимости, пока снова и снова не выходит за пределы функции, затем именованные вещи окружающего объекта (методы в данном случае), а затем в глобальные имена (в данном случае функции, если только вы не были глупы и не перегружены (), которые я игнорирую), а затем в пространстве имен std, если вы использовали строку using namespace std;. У меня могут быть последние два в неправильном порядке (std может искаться перед глобальным), но вам следует избегать написания кода, который зависит от этого.

person nategoose    schedule 15.04.2010

cout логически определен в iostream. Логически я имею в виду, что он может быть в файле iostream или в каком-то файле, включенном из iostream. В любом случае, включение iostream — правильный способ получить определение cout.

Все символы в iostream находятся в пространстве имен std. Чтобы использовать символ cout, вы должны указать компилятору, как его найти (т.е. какое пространство имен). У вас есть несколько вариантов:

// explicit
std::cout << std::endl;

// import one symbol into your namespace (other symbols must still be explicit)
using std::cout;
cout << std::endl;

// import the entire namespace
using namespace std;
cout << endl;

// shorten the namespace (not that interesting for standard, but can be useful
// for long namespace names)
namespace s = std;
s::cout << s::endl;
person R Samuel Klatchko    schedule 15.04.2010

#include <iostream> ссылается на заголовочный файл, определяющий cout. Если вы собираетесь использовать cout, вам всегда понадобится включить.

Вам не нужно using namespace std;. Это просто позволяет вам использовать сокращения cout и endl и т.п., а не std::cout и std::endl, где пространство имен указано явно. Лично я предпочитаю не использовать using namespace ..., так как это требует от меня ясности в моем значении, хотя, по общему признанию, это более многословно.

person andand    schedule 15.04.2010
comment
Компромисс — using std::cout; using std::endl;, после чего можно использовать cout и endl без уточнения, не приводя все пространство имен std в глобальное пространство имен. - person David Thornley; 15.04.2010