Использование пространства имен std - PullRequest
2 голосов
/ 21 мая 2011

Я учусь на уроке программирования в школе и хочу начать заниматься программированием на С ++ вне класса.В моей школе используется Microsoft Visual C ++ 6.0 (выпущенная в 1998 году), поэтому она по-прежнему использует <iostream.h>, а не <iostream> и using namespace std.Когда я начал работать, я не мог понять, как и когда использовать using namespace std, а когда просто использовать такие вещи, как std::cout<<"Hello World!"<<'\n'; (например), а также его ограничения и другие варианты использования для ключевого слова пространства имен.В частности, если я хочу создать программу с использованием iostream и iomanip, нужно ли мне дважды указывать «используя пространство имен std», или есть что-то другое, что я должен использовать, или я могу сделать то же самое, что иЯ сделал с iostream?Я пытался погуглить, но ничего не понял.Заранее спасибо за помощь.

Ответы [ 5 ]

11 голосов
/ 21 мая 2011

Ладно, там куча всего, но это управляемо.

Во-первых, разница между:

using namespace std;
...
cout << "Something" << endl;

И используя

std::cout << "Something" << std::endl;

Это просто вопрос объема. Scope - это просто причудливый способ сказать, как компилятор распознает имена переменных и функций, среди прочего. Пространство имен делает не что иное, как добавление дополнительного слоя области видимости ко всем переменным в этом пространстве имен. Когда вы набираете using namespace std, вы берете все внутри пространства имен std и перемещаете его в глобальную область, так что вы можете использовать более короткий cout вместо более полного std::cout.

Одна вещь, которую нужно понять о пространствах имен, это то, что они растягиваются по файлам. И <iostream>, и <iomanip> используют пространство имен std. Поэтому, если вы включите оба, объявление using namespace std будет работать с обоими файлами, и все символы в обоих файлах будут перемещены в глобальную область вашей программы (или область действия функции, если вы использовали ее внутри функции) .

Будут люди, которые скажут вам "не используйте using namespace std !!!!", но они редко говорят вам, почему. Допустим, у меня есть следующая программа, в которой все, что я пытаюсь сделать, это определить два целых числа и распечатать их:

#include <iostream>

using namespace std;

int main(int argc, char** argv) {
    int cout = 0;
    int endl = 1;
    cout << cout << endl << endl;     // The compiler WILL freak out at this :)
    return 0;
}

Когда я использую using namespace std, я открываю дверь для именования коллизий. Если я (случайно) назвал переменную, совпадающую с той, что была определена в заголовке, то ваша программа сломается, и вам будет непросто понять, почему.

Я могу написать ту же программу, что и раньше (но заставить ее работать), не используя оператор using namespace std:

#include <iostream>

int main(int argc, char** argv) {
    int cout = 0;
    int endl = 1;
    std::cout << cout << endl << std::endl; // Compiler is happy, so I'm happy :)
    return 0;
}

Надеюсь, это прояснило несколько вещей.

4 голосов
/ 21 мая 2011

Если вы используете имена заголовков без .h, то материал, объявленный / определенный в нем, будет находиться в пространстве имен std. Вы должны использовать using namespace std; только один раз в области, где вы хотите импортировать материал, чтобы получить все; больше чем один using namespace std; ничего не помогает.

Я бы рекомендовал против using namespace std; в целом, хотя. Вместо этого я предпочитаю говорить, например, using std::cout;, чтобы имена в std не конфликтовали с моими.

Например:

#include <iostream>
#include <iomanip>    

int main()
{
     using namespace std;

     int left = 1, right = 2;
     cout << left << " to " << right << "\n";
}

может вызвать загадочные проблемы, потому что left и right существуют в пространстве имен std (как манипуляторы ввода-вывода), и они импортируются, если вы лениво говорите using namespace std;. Если вы намеревались использовать манипуляторы ввода-вывода, а не выводить переменные, вы можете быть немного разочарованы. Но намерение не очевидно в любом случае. Может быть, вы просто забыли, что у вас есть целые числа с именами left и right.

Вместо этого, если вы скажете

#include <iostream>
#include <iomanip>

int main()
{
    using std::cout;

    int left = 1, right = 2;
    cout << left << " to " << right << "\n";
}

или

#include <iostream>
#include <iomanip>

int main()
{
     int left = 1, right = 2;
     std::cout << left << " to " << right << "\n";
}

все работает как положено. Кроме того, вы можете увидеть, что вы на самом деле используете (что, в данном случае, не включает в себя ничего из <iomanip>), так что легче будет обрезать ваши включения до того, что вам нужно.

1 голос
/ 21 мая 2011

Хороший вопрос, Райан. using namespace выполняет импорт всех символов из заданного пространства имен (области) в область, где он использовался. Например, вы можете сделать следующее:

namespace A {
  struct foo {};
}

namespace B {
  using namespace A;

  struct bar : foo {};
}

В приведенных выше примерах все символы в пространстве имен A становятся видимыми в пространстве имен B, как они были объявлены там.

Этот импорт влияет только на данную единицу перевода. Так, например, когда в вашем файле реализации (т.е. .cpp) вы делаете using namespace std;, вы в основном импортируете все символы из пространства имен std в глобальную область.

Вы также можете импортировать определенные символы, а не все, например:

using std::cout;
using std::endl;

Вы можете сделать это в глобальной области видимости, области имен или области функций, например:

int main ()
{
   using namespace std;
}

Программист должен решить, когда использовать полные имена и когда использовать ключевое слово using. Обычно помещать using в заголовочные файлы очень неприятно. Профессиональные программисты на C ++ почти никогда не делают этого, если только это не необходимо для обхода какой-либо проблемы, или они на 100% уверены, что это не испортит разрешение типов для тех, кто использует этот заголовок.

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

Также могут быть некоторые длинные пространства имен, и в этих случаях удобно использовать псевдонимы пространства имен. Например, есть библиотека Boost.Filesystem, которая помещает все свои символы в пространство имен boost::filesystem. Использование этого пространства имен было бы слишком много, поэтому люди обычно делают что-то вроде этого:

namespace fs = boost::filesystem;

fs::foo ();
fs::bar ();

Кроме того, почти нормально использовать псевдонимы пространства имен в заголовках, например:

namespace MyLib {
  namespace fs = boost::filesystem;
}

.. и получайте меньше печатания. В результате пользователи, которые будут использовать этот заголовок, не будут импортировать всю библиотеку файловой системы, говоря using namespace MyLib;. Но затем они импортируют пространство имен "fs" из вашей библиотеки, которое может конфликтовать с чем-то другим. Так что лучше этого не делать, но если вы хотите этого слишком сильно, это лучше, чем сказать using namespace boost::filesystem там.

Итак, вернемся к вашему вопросу. Если вы пишете библиотеку, используя потоки ввода / вывода C ++, лучше не иметь никаких using операторов в заголовках, и я бы пошел с using namespace std; в каждом cpp файле. Например:

somefile.hpp:

namespace mylib {

class myfile : public std::fstream {
public: 
  myfile (const char *path);

 // ...
};

}

somefile.cpp:

#include "somefile.hpp"

using namespace std;
using namespace mylib;

myfile::myfile (const char *path) : fstream (path)
{
  // ...
}
1 голос
/ 21 мая 2011

Специально для using namespace std

Вы действительно никогда не должны использовать его в заголовочном файле. Таким образом, вы импортировали весь «std» в глобальное пространство имен для всех, кто включает ваш заголовочный файл, или для всех, кто включает файл, содержащий ваш файл.

Использование его в файле .cpp - это личное предпочтение. Обычно я не импортирую весь std в глобальное пространство имен, но, кажется, нет никакого вреда в том, чтобы делать это самостоятельно, чтобы сэкономить немного времени на печать.

1 голос
/ 21 мая 2011

Здесь - это хорошая ссылка, которая описывает пространства имен и как они работают.

Оба метода верны, то есть вы можете либо ввести пространство имен с помощью оператора using, либо можете квалифицировать всех членов пространства имен.Это вопрос стиля кодирования.Я предпочитаю уточнять пространства имен, потому что это дает читателю понять, в каком пространстве имен определена функция / класс.

Кроме того, вам не нужно вводить пространство имен дважды, если вы включаете несколько файлов.Достаточно одного заявления об использовании.

...