Почему все используют незанятые объявления пространства имен (то есть std:: not::std::)?
Мне кажется, что использование незанятых пространств имен просто вызывает проблемы позже, когда кто-то вставляет новое пространство имен, которое, как оказалось, имеет то же имя, что и пространство имен корневого уровня, и таинственным образом меняет смысл целого ряда программ. Итак, почему люди всегда говорят std::
вместо ::std::
, Они действительно хотят сказать: "Я хочу использовать что угодно std
удобно, а не root."?
Вот пример того, что я имею в виду:
В fred/Foo.h:
#include <string>
namespace fred {
class Foo {
public:
void aPublicMember(const std::string &s);
};
} // end namespace fred
В фред /Bar.h:
namespace fred {
namespace std { // A standard fred component
class string { // Something rather unlike the ::std::string
// ...
};
} // namespace std
class Bar {
public:
void aPublicMember(std::string &s);
};
} // namespace fred
В oops.cpp:
#include <string>
#include "fred/Bar.h"
#include "fred/Foo.h" // Oops, the meaning of Foo is now different.
Это то, что люди хотят, или я что-то упускаю?
А может быть, вы говорите, что никогда не должны называть пространство имен std
, И это все хорошо, но что тогда с другим пространством имен корневого уровня? Должно ли какое-либо пространство имен корневого уровня, которое кто-либо когда-либо определил где-либо, всегда быть запрещенным для имени под-пространства имен?
Чтобы уточнить, я не буду рассматривать любой ответ, который говорит мне std
особенный, потому что я просто использовал его в качестве примера. Я говорю об общей проблеме, и я использую std
в качестве опоры, чтобы проиллюстрировать это, хотя я признаю, что это довольно поразительная опора.
8 ответов
Практическая причина незанятых пространств имен заключается в том, что обычно достаточно одного уровня пространств имен. Когда это не так, второй уровень обычно будет использоваться для деталей реализации. И, наконец, даже при использовании нескольких уровней они все же обычно указываются неявно от корневого уровня. то есть. даже внутри пространства имен ns1
вы бы обычно ссылались на ns1::ns2::foo
вместо ns2::foo
или же ::ns1::ns2::foo
,
Итак, по этим трем причинам ::ns1
форма избыточна в обычных случаях. Единственный случай, когда я рассмотрю это, будет в материалах Boost, потому что, как автор Boost, я не буду знать, где будет использоваться мое программное обеспечение.
Итак, почему люди всегда говорят std:: вместо:: std::
Возможно, потому что у них никогда не было проблем с неопределенностью из-за этого.
В том же духе: мне никогда не приходилось включать "землю" в свой адрес, и я не собираюсь этого делать.
Вы должны провести черту где-нибудь, и это разумное предположение, что другие не будут создавать свои собственные пространства имен std, или, по крайней мере, библиотека, которая не будет очень популярной.:)
почему люди всегда говорят std::
Не всегда. я использую string
а также using ::std::string
, Так что ничего страшного если не будет fred::std::string
, потому что я все еще использую std::string
, В небольших cpp-файлах это может быть даже using namespace ::std
, Образец:
#include <iostream>
using ::std::string;
//using namespace ::std; // good for small cpp-files
int main()
{
string s = "sometext"; // no leading ::std
}
Вы никогда не должны называть пространство имен стандартным
Да не стоит давать имя std
в произвольное пространство имен.
Это настолько искусственно:
namespace fred {
namespace std { // A standard fred component
class string { // Something rather unlike the ::std::string
// ...
};
} // namespace std
} // namespace fred
Этот Фред не сможет объяснить, почему он сделал это для всей команды.
Чтобы ответить на ваш вопрос: люди сначала опускают "::", потому что это привычка, которая экономит время и потому что легче ожидать, что когда пространство имен используется где-либо, такое имя является абсолютным, а не относительным.
Хорошо, вы говорите, что std
это только пример. Но мне кажется, что ваш вопрос применим только к случаю, когда кто-то делает что-то такое же зло, как и превосходящее std
,
Позвольте мне привести еще один пример:
namespace logging
{
// Logs to local file
}
namespace server
{
namespace logging
{
// Logs to remote destination
}
}
namespace client
{
namespace logging
{
// Logs to local file and to screen
}
}
В этом случае не предваряя ::
приводит к поведению по умолчанию.
Много кода написано в глобальном пространстве имен. Если кто-то действительно переопределит:: std::, не имеет значения, как вы к нему обращаетесь в таком коде.
Кроме того, ваш сценарий маловероятен и его легко обойти. Во-первых, условность, поскольку существовало "стандартное правило", заключалась в том, что вы не используете это имя. Во-вторых, если вы столкнулись с пакетом, который определил пространство имен 'std', вы просто делаете это:
#include <package_name.hpp>
namespace package_name {
using namespace std;
}
namespace my_app {
class my_class : public package_name::class_of_something {};
}
Или что-то подобное. Возможно, вам придется явно назвать:: std как std. Моя точка зрения такова: люди все время используют не привязанный 'std::', потому что даже наихудшие последствия не имеют большого значения, и вряд ли в этом.
В случае std
Я бы не стал использовать другое пространство имен с тем же именем, теми же классами, но с другим значением.
В других случаях ведущие ::
просто выглядит некрасиво и затрудняет чтение кода (на мой взгляд). Столкновения пространства имен слишком редки, чтобы ::
перед всем.
Точно так же, как имена с префиксом _
зарезервированы, рассмотрим std::
так хорошо, как защищены.