Немножко о using namespace std: почему ругают и чем плохо

  • Почему using namespace std плохо
У всех, наверное, студентов, начавших изучать C++, в первые же дни возникает вопрос об этом "странном" using namespace std: что это такое, почему одни пишут так, а другие вот так?
  • namespace — это пространство имён
C++ — это такой язык программирования, в котором очень широко используют различные подключаемые файлы. Даже чтобы просто вывести текст на экран, люди подключают, например, или файл iostream, или cstdio (наследие языка Си). В таких файлах широко применяются глобальные сущности. Одним файлом всё не ограничивается, подключают файлы очень часто, а написаны эти файлы очень разными программистами, друг о друге часто даже не знающими. Так как программисты часто не знают друг о друге и не связаны друг с другом никакими отношениями, то и в кодах их могут оказаться одноимённые сущности.

Пётр и Вася написали два каких-то кода, в которых оказались два одноимённых класса.

Чтобы это написать, нужно знать, как писать программы, разделённые на файлы.
Если попробовать собрать проект из показанных кодов, скомпилировать программу и попробовать её запустить, то будет неудача, этот пример не компилируется. Возникает проблема: повторение имени. Нельзя давать одинаковые имена разным сущностям. Директива #include — это указание компилятору вписать текст из указанного файла в текущее место кода. Формально выполняется обычная подстановка текстов обоих файлов в основную программу. Происходит разворачивание в один кусок текста:

Код основной программы при компилировании выглядит вот так:

MyClass объявлен дважды, что и порождает проблему.
Самый очевидная борьба с таким проявлением недоразумения — давать очень длинные имена названиям, используя всевозможные приставки, суффиксы и что-нибудь ещё. Есть только маленькое но — применение такого способа не только не даёт гарантий, что не случится несовпадения, но и громоздит код.
В С++ возможно избежать такой проблемы достаточно простым способом. Можно создать что-то наподобие срезов глобальной области. Эти срезы с одной стороны относятся к глобальной области, с другой стороны глобальными областями не являются. Можно сказать, что глобальное пространство разбивается на границы. Получаются глобальные участки. Я надеюсь, что вы поняли то, о чём я успел написать. Дальше идёт вторая ступенька этой темы.

Если написать эту программу и запустить, то всё пройдёт гладко.
Таким образом решают проблему конфликтов в именовании. Оттсюда берёт своё начало namespace std; Теперь свободно можно использовать область видимости:

А вот сейчас тот самый момент, который является причиной НЕиспользования такого способа. Несмотря на то, что пространства имён различны, включение второго пространства имён может привести к тому, от чего так старательно уходили создатели языка, придумывая решение именно этой проблемы:

Этот последний код просто откажется компилироваться, именно потому что дважды объявлен класс MyClass. Здесь происходит обратный эффект: изначально внутри файлов глобальная территория была поделена на независимые территории, а внутри основной программы буквально говорят: давай мне все территории сразу, они мне все нужны. В итоге случается недоразумение, которое выше было описано. Жадность — начало местной беды.
Именно по этой причине использование формы using namespace std; так сильно прессуется опытными программистами. Ведь программист, который пишет другой код, не обязан знать обо всём, что написано в пространстве имён std или в файлах Петра и Васи. Теперь, полагаю, читателю легче понять, что существует большой риск повторения имён.
Даже вот в таком виде, проблема остаётся:

Именно поэтому чаще всего всё сводится к узкой локализации в конкретном, в нужном месте:

Вот такая банальная причина нужна, чтобы протестовать против общеупотребимой новичками формы. Да, это быстро, удобно писать, код читабельней выглядит, но в то же время такая манера "жадного" написания кода даёт эффект описанной ошибки.
Если кода изначально написано много, а в нём использован "жадный способ" то при добавлении ещё одного файла к проекту дописывать для каждого места то, что изначально было опущено, может оказаться не самым приятным делом. Сам я не программист, поэтому не имел с этим практики, но последняя мысль моя вряд ли далека от истинны. Хотя, конечно, может я ошибся в таком выводе.
Речь немного о другом: чтобы избежать случайного включения какого-либо объявления, лучше использовать прямые описания.
Жадный способ — это способ, который употребим новичками: using namespace std; Жадным назван только мной, потому что буквально он и есть жадный: когда глобальная сущность поделена на кусочки, этот способ норовит взять всю глобальную сущность: "и для кого резали?" — спрашивается. Это несуществующий сейчас термин, моего авторства, не специалистов.
Но в подавляющем большинстве случаев лучше сразу привыкать к прямому описанию. На этом сайте в основном используется "жадная форма". Это для удобочитаемости, но не потому что это хорошо.
Ещё одна причина некоторой нелюбви к непрямому указанию пространства имени — это возможное перекрытие переменной.

Вот в таком, например, примере всё работает. Но есть один момент, здесь объявлена глобальная переменная: символьный массив а, инициализированный значением ::a. Ведь автор кода мог справедливо надеяться на то, что внутри его функций будет задействована общая глобальная переменная со значением ::a. А внутри функций, неожиданно для него, задействуются переменные из пространств имён. Это такой вид ошибок, когда всё работает, но что-то идёт не так, самый противный и нелюбимый всеми. Очень сложно словить такие ошибки в программах.
Здесь кода мало и программа маленькая, поэтому и исправить всё это очень легко, нужно использовать прямое обращение к глобальному пространству.
Вот пример более полного кода на самостоятельный разбор. Лучше этот код разбирать комментируя участки кода в main. Я поделил эти участки на группы по три строки, один такой блок закомментировал.

Это пример показывает не только почему использование не самого прямого пространства имён плохо/ненадёжно, но и вообще вскрывает некоторую проблему глобальных имён. Использование пространств имён с явным прописыванием способствует написанию кода без особых головных болей. Как видно в примере, даже для глобальной переменной иногда имеет смысл использовать явное указание пространства имён, в функции foo() строка кода закомментирована, где конфликт имён. Как этот пример представить проще я не придумал, поэтому смотрите на его работу, комментируя блоки в main, и вникая в происходящее.
Мне остаётся надеяться, что эта тема была интересной и помогла разобраться в каких-то моментах. Используйте прямые обращения к пространствам имён, и, возможно, вы избавите себя от трудноуловимой ошибки.

Один комментарий на «“Немножко о using namespace std: почему ругают и чем плохо”»

  1. увася:

    пипос, место того, чтобы ты расписал побольше как что и где, ты расписал за что тебя могут прессинговать коллеги по работе или кто там, какие у вас норм пасанские правила и что это и что то жзначит про тебя как про человека, жаден ты или что хе

     

    это называется свехнутся и нерубить суть.

    читал с удовольствием суть ты донёс спс

    2
    8

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/byarne-straustrup/dizayn-i-evoluciya-yazyka-s-22852186/?lfrom=15589587

Последние комментарии

Яндекс.Метрика