Из (Неофициальный) Справочник по видам Python :
Публичные имена, определенные модулем, определяются путем проверки пространства имен модуля для переменной с именем
blockquote>__all__
; если определено, это должна быть последовательность строк, которые являются именами, определенными или импортированными этим модулем. Имена, приведенные в__all__
, считаются общедоступными и должны существовать. Если__all__
не определен, набор общедоступных имен включает все имена, найденные в пространстве имен модуля, которые не начинаются с символа подчеркивания («_»).__all__
должен содержать весь открытый API. Он предназначен для предотвращения случайного экспорта элементов, которые не являются частью API (например, библиотечные модули, которые были импортированы и использованы в модуле).
В C++
понятия являются отдельными. Это по замыслу и полезно.
Вы можете включить вещи, которые без пространств имен были бы неоднозначными.
С помощью пространств имен вы можете ссылаться на два разных класса с одинаковыми именами. Конечно, в этом случае вы не будете использовать директиву using
, или, если вы это сделаете, вы должны будете указать пространство имен других элементов в требуемом пространстве имен.
Обратите внимание, что вам НЕ НУЖНО использование - вы можете просто использовать std :: cout или все, что вам нужно для доступа. Вы вводите предметы в пространство имен.
Включение определяет существование функций.
Использование облегчает их использование.
cout
как определено в iostream, фактически называется "std :: cout".
Вы можете избежать использования пространства имен, написав.
std::cout << "Hello World";
Я думаю, что другие ответы немного упускают суть. Во всех C ++, Java и C # вещь using
/ import
совершенно необязательна. Так что это не отличается.
А затем вы должны сделать что-то еще, чтобы код был видимым на всех трех платформах.
В C ++ вам необходимо минимально включить его в текущий модуль перевода (достаточно для многих реализаций вектора, строки и т. Д.), Часто вам также необходимо добавить что-то в свой компоновщик, хотя некоторые библиотеки делают это автоматически основано на включении (например, повышение при сборке на Windows).
А в C # вы должны добавить ссылку на другую сборку. Это позаботится об эквиваленте включений и настроек ссылок.
А в Java вы должны убедиться, что код находится на пути к классам, например, добавив к нему соответствующий кувшин.
Таким образом, на всех трех платформах требуются очень похожие вещи, и разделение между using
/ import
(удобство) и фактическим разрешением связи (требование) одинаково во всех трех.
Вам нужно понять пространства имен , если вы хотите по-настоящему понять это.
С помощью include
вы просто включаете заголовочный файл.
С помощью using namespace
вы заявляете, что используете заданное пространство имен, содержащее такие вещи, как cout. поэтому, если вы сделаете это:
using namespace std;
вы используете cout
, вы можете просто сделать
cout << "Namespaces are good Fun";
вместо:
std::cout << "Namespaces are Awesome";
Обратите внимание, что если вы не делайте #include <iostream>
, вы не сможете использовать ни std::cout
, ни cout
в своих декларациях и т. д., потому что вы не включаете заголовок.
Как уже говорилось, C ++ и Java - это разные языки, и они делают несколько разные вещи. Кроме того, C ++ больше похож на язык «изящного роста», а Java - больше на разработанный язык.
Хотя using namespace std;
не обязательно является плохой идеей, использование его для всех пространств имен исключит всю выгоду. Пространства имен существуют для того, чтобы вы могли писать модули без учета столкновений имен с другими модулями, а using namespace this; using namespace that;
может создавать неоднозначности.
Эти ключевые слова используются для разных целей.
Ключевое слово using делает имя из пространства имен доступным для использования в текущем декларативном регионе. Это в основном для удобства, чтобы вам не приходилось постоянно использовать полное имя. Эта страница объясняет это в некоторых деталях.
Инструкция #include является директивой препроцессора, и она указывает препроцессору обрабатывать содержимое указанного файла так, как если бы это содержимое появилось в исходной программе в тот момент, когда появляется директива. То есть вы можете думать об этом заявлении как о копировании включенного файла в текущий. Затем компилятор компилирует весь файл так, как будто вы записали весь код в один большой файл.
Использование директив и включение директив препроцессора - это две разные вещи. include
примерно соответствует переменной среды CLASSPATH
Java или опции -cp
виртуальной машины Java.
То, что он делает, делает типы известными компилятору. Например, включение <string>
позволит вам ссылаться на std::string
:
#include <string>
#include <iostream>
int main() {
std::cout << std::string("hello, i'm a string");
}
. Теперь использование директив похоже на import
в Java. Они делают имена видимыми в той области, в которой они появляются, поэтому вам больше не нужно полностью их квалифицировать. Как и в Java, используемые имена должны быть известны прежде, чем их можно будет сделать видимыми:
#include <string> // CLASSPATH, or -cp
#include <iostream>
// without import in java you would have to type java.lang.String .
// note it happens that java has a special rule to import java.lang.*
// automatically. but that doesn't happen for other packages
// (java.net for example). But for simplicity, i'm just using java.lang here.
using std::string; // import java.lang.String;
using namespace std; // import java.lang.*;
int main() {
cout << string("hello, i'm a string");
}
Это плохая практика - использовать директиву using в заголовочных файлах, потому что это означает, что любой другой исходный файл, который включает его, будет увидеть эти имена, используя поиск без определения имени. В отличие от Java, где вы делаете имена видимыми только для пакета, в котором появляется строка импорта, в C ++ это может повлиять на всю программу, если они включают этот файл прямо или косвенно.
Будьте осторожны, когда делаете это в глобальном масштабе, даже в файлах реализации. Лучше использовать их как можно более локально. Для пространства имен std я никогда не использую это. Я и многие другие люди просто пишем std::
перед именами. Но если вам случится это сделать, сделайте это следующим образом:
#include <string>
#include <iostream>
int main() {
using namespace std;
cout << string("hello, i'm a string");
}
Что такое пространства имен и зачем они вам нужны, пожалуйста, прочитайте предложение, предложенное Бьярном Страуструпом в 1993 году для добавления их в предстоящий C ++. Стандарт. Хорошо написано:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0262.pdf
Даже Страуструп называет механизм #include
несколько хакерским. Однако это значительно упрощает раздельную компиляцию (поставляйте скомпилированные библиотеки и заголовки вместо всего исходного кода).
На самом деле вопрос заключается в том, «почему C ++ - после того, как у него уже был механизм #include
- добавил пространства имен?»
Лучший из известных мне примеров того, почему #include
недостаточно, приходит от вс. Очевидно, у разработчиков Sun были некоторые проблемы с одним из их продуктов, потому что они написали функцию mktemp()
, у которой была та же сигнатура, что и у функции mktemp()
, которая была включена из файла, который сам был включен через заголовок, на самом деле проект хотел.
Конечно, эти две функции были несовместимы, и одну нельзя было использовать вместо другой. С другой стороны, компилятор и компоновщик не осознавали этого при сборке двоичного файла, и иногда mktemp()
вызывал одну функцию, а иногда вызывал другую, в зависимости от порядка компиляции или компоновки различных файлов.
Проблема связана с тем фактом, что C ++ изначально был совместим с C и, по сути, поддерживал его. C и C имеет только глобальное пространство имен. C ++ решил эту проблему - в коде, который не совместим с C - через пространства имен.
И C #, и Java (1) имеют механизм пространства имен (namespace
в C #, package
в Java), (2) обычно разрабатываются с помощью IDE, которые обрабатывают ссылки на двоичные файлы для разработчика, и (3) don не разрешать автономные функции (область действия класса является чем-то вроде пространства имен и снижает риск загрязнения глобального пространства имен), поэтому у них есть другое решение этой проблемы. Однако все еще возможно иметь некоторую двусмысленность относительно того, какой метод вы вызываете (скажем, конфликт имен между двумя интерфейсами, которые наследует класс), и в этом случае все три языка требуют, чтобы программист четко указал, какой метод они вызывают. на самом деле ищет, обычно добавляя родительский класс / имя интерфейса.
В C ++ #include
и использование имеют разные функции.
#include
помещает текст включенного файла в ваш исходный файл (на самом деле блок перевода ), а пространства имен с другой стороны - это просто механизм, позволяющий иметь уникальные имена, чтобы разные люди могли создавать " foo "объект.
Это происходит из-за того, что C ++ не имеет понятия модуля.
Имейте в виду, что пространства имен в C ++ открыты, это означает, что разные файлы могут определять разные части одного и того же пространства имен (что-то вроде частичных классов .NET).
//a.h
namespace eg {
void foo();
}
//b.h
namespace eg {
void bar();
}
Одна строка (не то, что это что-то новое:)):
с использованием std позволяет вам пропустить префикс std :: , но вы не можете использовать cout вообще без iostream .
В C ++ директива include скопирует и вставит файл заголовка в ваш исходный код на этапе предварительной обработки. Следует отметить, что заголовочный файл обычно содержит функции и классы, объявленные в пространстве имен. Например, заголовок <vector>
может выглядеть примерно так:
namespace std {
template <class T, class Allocator = allocator<T> > class vector;
...
}
Предположим, вам нужно определить вектор в вашей основной функции, вы делаете #include <vector>
и у вас есть фрагмент кода выше в вашем коде сейчас:
namespace std {
template <class T, class Allocator = allocator<T> > class vector;
...
}
int main(){
/*you want to use vector here*/
}
Обратите внимание, что в вашем коде векторный класс все еще находится в пространстве имен std
. Однако ваша основная функция находится в пространстве имен по умолчанию global
, поэтому простое включение заголовка не сделает векторный класс видимым в пространстве имен global
. Вы должны либо использовать using
, либо сделать префикс, например, std::vector
.