#новичкам
Десятки новичков спрашиваются в комментариях что это за конструкция и почему никто в более менее серьезном коде не использует ее. Ну чтож. Мы долго игнорировали этот запрос, но пора это исправить. Пост с разъяснениями просто обязан существовать. Поэтому сегодня все по полочкам разложим.
Начнем с namespace
В большинстве современных языков так или иначе реализована возможность разделения подключаемой функциональности на какие-то логические части. Отчасти это сделано для того, чтобы непосредственно в коде можно было увидеть к какой части принадлежит функциональность.
В С++ тоже есть похожий механизм. Он называется пространство имен или namespace. Можно сказать, что это область, где вы можете определять сущности, логически связанные друг с другом.
Работает это примерно так:
namespace MyLib {
void hello() { ... }
}
MyLib::hello();Мы определяем пространство имен MyLib, в котором будут все функции, классы и переменные, которые относятся только к этой либе. И при использовании функции hello мы обязаны указать перед ее именем неймспейс MyLib, чтобы компилятор понимал, где ему искать эту функцию.
Заодно и все, кто читает код, теперь понимают, что мы использует функцию hello именно из пространства MyLib и ни откуда-нибудь еще. Потому что может случиться ситуация, когда функция с именем hello будет не только в этом пространстве:
void hello() { ... }
namespace MyLib {
void hello() { ... }
}
namespace OtherLib {
void hello() { ... }
}
MyLib::hello();Вот сейчас критически важно указать, из какого пространства функция вызывается, потому что вы просто можете вызывать не ту функцию, если ничего не укажите.
Теперь std.
Это пространство имен для сущностей, которые уже реализованы за вас в стандартной библиотеке.
Допустим, вы хотите что-то на консоль вывести. Вы подключаете заголовочник
<iostream> и используете глобальный объект cout из пространства имен std:#include <iostream>
int main() {
std::cout << "Hello, World!\n";
}
Вы сами не реализовывали cout. Вы лишь использовали то, что уже существует в стандартной библиотеке. И сказали об этом с помощью указания пространства имен.
Теперь using.
Иногда у пространств имен бывают очень длинные названия. Плюс они могут быть вложены друг в друга. И не всегда хочется писать:
my_library::my_cool_module::my_class obj;
И если вы знаете, что:
1️⃣ в данном конкретном небольшом месте кода вы используете много сущностей из какого-то пространства имен
2️⃣ и нет никакой неоднозначности, как в примере с функцией hello
вы можете использовать конструкцию using namespace:
void foo() {
using namespace my_library::my_cool_module;
my_cool_class obj;
my_other_cool_class = my_cool_function(obj);
}С ее помощью вы говорите компилятору: "Внутри этого блока кода я могу использовать сущности из этого пространства имен без префикса. Ищи неизвестные тебе имена там."
Ну а конструкция
using namespace std говорит о том, что мы можем использовать абсолютно все стандартные сущности без указания префикса.Почему же так никто не делает, если это избавляет от головной боли писать постоянно
std::?👉🏿 Код пишется для того, чтобы его читали. При указании неймспейса читатель сразу понимает, откуда берется данная сущность. Это улучшает читаемость.
👉🏿 Обузинг
using namespace особенно в глобальном скоупе(вне функции и другого пространства имен) чреват конфликтом имен:void hello() {}
namespace MyLib {
void hello() {}
}
using namespace MyLib;
hello();компилятор просто не поймет, какую функцию вы хотите реально вызывать. В данном случае будет ошибка компиляции. Но при определенных условиях компилятор может вызвать не ту версию и даже никак не сообщить вам об этом. Дебагаться потом будете долго.
👉🏿 Положите
using namespace std в свой хэдэр и теперь проблемы будут у всего кода, который его подключает.В боевом коде почти никто не использует эту конструкцию, поэтому учитесь писать сразу так, как это будет требоваться в будущем.
Ease is not always the best choice. Stay cool.
#cppcore #badpractice