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

Из (Неофициальный) Справочник по видам Python :

Публичные имена, определенные модулем, определяются путем проверки пространства имен модуля для переменной с именем __all__ ; если определено, это должна быть последовательность строк, которые являются именами, определенными или импортированными этим модулем. Имена, приведенные в __all__, считаются общедоступными и должны существовать. Если __all__ не определен, набор общедоступных имен включает все имена, найденные в пространстве имен модуля, которые не начинаются с символа подчеркивания («_»). __all__ должен содержать весь открытый API. Он предназначен для предотвращения случайного экспорта элементов, которые не являются частью API (например, библиотечные модули, которые были импортированы и использованы в модуле).

blockquote>

29
задан duli 23 December 2008 в 20:04
поделиться

11 ответов

В C++ понятия являются отдельными. Это по замыслу и полезно.

Вы можете включить вещи, которые без пространств имен были бы неоднозначными.

С помощью пространств имен вы можете ссылаться на два разных класса с одинаковыми именами. Конечно, в этом случае вы не будете использовать директиву using, или, если вы это сделаете, вы должны будете указать пространство имен других элементов в требуемом пространстве имен.

Обратите внимание, что вам НЕ НУЖНО использование - вы можете просто использовать std :: cout или все, что вам нужно для доступа. Вы вводите предметы в пространство имен.

27
ответ дан Rann Lifshitz 23 December 2008 в 20:04
поделиться

Включение определяет существование функций.

Использование облегчает их использование.

cout как определено в iostream, фактически называется "std :: cout".

Вы можете избежать использования пространства имен, написав.

std::cout << "Hello World";
6
ответ дан James Curran 23 December 2008 в 20:04
поделиться

Я думаю, что другие ответы немного упускают суть. Во всех C ++, Java и C # вещь using / import совершенно необязательна. Так что это не отличается.

А затем вы должны сделать что-то еще, чтобы код был видимым на всех трех платформах.

В C ++ вам необходимо минимально включить его в текущий модуль перевода (достаточно для многих реализаций вектора, строки и т. Д.), Часто вам также необходимо добавить что-то в свой компоновщик, хотя некоторые библиотеки делают это автоматически основано на включении (например, повышение при сборке на Windows).

А в C # вы должны добавить ссылку на другую сборку. Это позаботится об эквиваленте включений и настроек ссылок.

А в Java вы должны убедиться, что код находится на пути к классам, например, добавив к нему соответствующий кувшин.

Таким образом, на всех трех платформах требуются очень похожие вещи, и разделение между using / import (удобство) и фактическим разрешением связи (требование) одинаково во всех трех.

4
ответ дан Daniel Earwicker 23 December 2008 в 20:04
поделиться

Вам нужно понять пространства имен , если вы хотите по-настоящему понять это.

С помощью include вы просто включаете заголовочный файл.

С помощью using namespace вы заявляете, что используете заданное пространство имен, содержащее такие вещи, как cout. поэтому, если вы сделаете это:

using namespace std;

вы используете cout, вы можете просто сделать

cout << "Namespaces are good Fun";

вместо:

std::cout << "Namespaces are Awesome";

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

3
ответ дан JohnIdol 23 December 2008 в 20:04
поделиться

Как уже говорилось, C ++ и Java - это разные языки, и они делают несколько разные вещи. Кроме того, C ++ больше похож на язык «изящного роста», а Java - больше на разработанный язык.

Хотя using namespace std; не обязательно является плохой идеей, использование его для всех пространств имен исключит всю выгоду. Пространства имен существуют для того, чтобы вы могли писать модули без учета столкновений имен с другими модулями, а using namespace this; using namespace that; может создавать неоднозначности.

3
ответ дан David Thornley 23 December 2008 в 20:04
поделиться

Эти ключевые слова используются для разных целей.

Ключевое слово using делает имя из пространства имен доступным для использования в текущем декларативном регионе. Это в основном для удобства, чтобы вам не приходилось постоянно использовать полное имя. Эта страница объясняет это в некоторых деталях.

Инструкция #include является директивой препроцессора, и она указывает препроцессору обрабатывать содержимое указанного файла так, как если бы это содержимое появилось в исходной программе в тот момент, когда появляется директива. То есть вы можете думать об этом заявлении как о копировании включенного файла в текущий. Затем компилятор компилирует весь файл так, как будто вы записали весь код в один большой файл.

4
ответ дан Vincent Ramdhanie 23 December 2008 в 20:04
поделиться

Использование директив и включение директив препроцессора - это две разные вещи. 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

39
ответ дан Johannes Schaub - litb 23 December 2008 в 20:04
поделиться

Даже Страуструп называет механизм #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 не разрешать автономные функции (область действия класса является чем-то вроде пространства имен и снижает риск загрязнения глобального пространства имен), поэтому у них есть другое решение этой проблемы. Однако все еще возможно иметь некоторую двусмысленность относительно того, какой метод вы вызываете (скажем, конфликт имен между двумя интерфейсами, которые наследует класс), и в этом случае все три языка требуют, чтобы программист четко указал, какой метод они вызывают. на самом деле ищет, обычно добавляя родительский класс / имя интерфейса.

2
ответ дан 2 revs 23 December 2008 в 20:04
поделиться

В C ++ #include и использование имеют разные функции.

#include помещает текст включенного файла в ваш исходный файл (на самом деле блок перевода ), а пространства имен с другой стороны - это просто механизм, позволяющий иметь уникальные имена, чтобы разные люди могли создавать " foo "объект.

Это происходит из-за того, что C ++ не имеет понятия модуля.

Имейте в виду, что пространства имен в C ++ открыты, это означает, что разные файлы могут определять разные части одного и того же пространства имен (что-то вроде частичных классов .NET).

//a.h
namespace eg {
    void foo();
}

//b.h
namespace eg {
    void bar();
}
9
ответ дан Manuel Selva 23 December 2008 в 20:04
поделиться

Одна строка (не то, что это что-то новое:)):

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

2
ответ дан PolyThinker 23 December 2008 в 20:04
поделиться

В 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.

2
ответ дан user2859314 23 December 2008 в 20:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: