Использование пространств имен и включает - PullRequest
0 голосов
/ 27 января 2019

Вопрос может быть тривиальным (и, возможно, дубликатом).

Насколько я понимаю, файл заголовка C / C ++ (с using namespace в нем), когда используется другими исходными файлами,он копируется прямо в тот момент, когда директива #include была в этом исходном файле.

Кроме того, учитывая, что в исходном файле используется относительно большое количество директив включения и что может быть несколько «переопределений»"для всей стандартной библиотеки (просто нацеленной на разные реализации).

Вот главный вопрос: Как узнать, какие пространства имен я в настоящее время использую в любой точке исходного файла, если исходный файлне имеет using namespace оператора?

Я читаю исходные файлы и понятия не имею, какое пространство имен используется.

Можно переопределить разумность пространства имен, используя что-то вроде::std::getline().

Если не существует простого способа определения пространства имен, будет ли справедливым рефакторинг этих файлов, например, когда вместо него будет использоваться stringч ::std::string?

Ответы [ 4 ]

0 голосов
/ 27 января 2019

Есть три подхода, о которых я могу подумать прямо сейчас:

Использование IDE : современная среда разработки должна иметь возможность (возможно, с помощью плагинов) анализировать вашикод во время редактирования и сообщит вам достоверное полное имя любого идентификатора, на который наведен курсор мыши.

Конечно, это не вариант, если вы не используете IDE, и иногда даже IDE могут запутатьсяи предоставит вам неверную информацию.

Используйте компилятор и догадки : Если у вас уже есть догадка, в каком пространстве имен вы могли бы находиться, вы можете определить какой-либо объект, сослаться на него по определенному имени ипосмотрите, компилируется ли код, например, так:

const int Fnord = 1;
const int* Probe = &::solid::guess::Fnord;

Одно предостережение в том, что он может дать неверные результаты, если задействованы using namespace или анонимные пространства имен.

Использовать препроцессор : большинство компиляторов определяют макрос препроцессора, который сообщает вам имя функции, в которой он используется, который может включать пространство имен;например, на MSVC __FUNCTION__ сделает именно это.Если файл содержит функцию, которая, как вы знаете, будет выполнена, вы можете заставить эту функцию сообщать вам свое авторитетное квалифицированное имя во время выполнения, например:

int SomeFunction(void)
{
    printf("%s\n", __FUNCTION__);
}

Если вы не можете использовать стандартный вывод,вы можете сохранить значение в переменной и использовать отладчик для его проверки.

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

(К сожалению, я не могу придумать, как проверить значение макроса во время компиляции; мне пришло в голову static_assert, но его нельзя использовать внутри функций, а __FUNCTION__ не можетиспользоваться снаружи.)

Макрос не стандартизирован, хотя и может не включать пространство имен (или он может вообще не существовать).Например, в GCC __FUNCTION__ даст вам только неквалифицированное имя, и вам придется использовать __PRETTY_FUNCTION__.

(Начиная с C99 и C ++ 11 существует стандартизированная альтернатива, __func__, но формат имени функции не указан и может включать или не включать пространство имен. В GCC это не так.)

0 голосов
/ 27 января 2019

Если у вас нет директивы using namespace ..., вы не используете пространство имен.В общем, ваш код должен ссылаться на вещи в стандартной библиотеке с их полными именами, например, std::cout, std::get_line(), std::string.

Да, вы можете сэкономить себе немного времени на печать за счетпотери ясности, а иногда и загадочных ошибок компиляции или, что еще хуже, ошибок времени выполнения с using namespace std;.После этого вам не нужно ставить std:: перед именами вещей в стандартной библиотеке: cout, get_line(), string.Директива using помещает эти имена в глобальное пространство имен вместе с кучей шламов, которые вам, вероятно, не интересны.

Если вы используете что-то вроде using namespace std;, оно должно отображаться only в исходном файле никогда в заголовке.Таким образом, вы можете узнать, какие пространства имен были «использованы», посмотрев вверху файла.Вам не нужно отслеживать все ваши заголовки на предмет отклонений, используя директивы.

0 голосов
/ 27 января 2019

using namespace не делает то, что вы ожидаете ...

Если вы хотите разместить функции, классы или переменные в пространстве имен, вы делаете это следующим образом:

namespace foo
{
    void f();
}
namespace bar
{
    void f();
}

Это объявляет две функции f в пространствах имен foo и bar соответственно.То же самое вы найдете в заголовочных файлах;если не указано пространство имен, указанное выше, функция / класс / переменная находится в глобальном пространстве имен.Ничего более.

using namespace теперь позволяет вам использовать функции из пространства имен, не указывая его явно:

// without:
foo::f();
bar::f();
f();      // unknown!

using namespace foo;
foo::f(); // still fine...
bar::f();
f();      // now you call foo::f

Помните, что это плохая практика Хотя (ссылка относится к пространству имен std, но то же самое относится и к всем пространствам имен).

Это еще хуже в заголовочных файлах: нет способа отменить эффектснова объявил using namespace <whatever> - так что вы навязываете его всем пользователям вашего заголовка, что может вызвать серьезные проблемы у некоторых из них.Поэтому, пожалуйста, никогда не используйте его в заголовочных файлах.

0 голосов
/ 27 января 2019

using namespace не означает, что вы используете это конкретное пространство имен.Это означает, что все типы, переменные и функции из этого пространства имен теперь находятся в вашем глобальном пространстве имен для этой единицы перевода.Таким образом, у вас может быть несколько таких операторов.

Вот почему заголовочные файлы никогда не должны использовать using namespace.Нет более простого способа, чем использовать std::string в заголовочном файле, вы всегда должны быть очень откровенны в отношении пространства имен без using namespace s.

Используя using namespace xxx, не существует способа выяснить, чтоБоюсь, xxx теперь находится в глобальном пространстве имен.

...