Подтвердить что ты не робот

Что касается глобального пространства имен в С++

В С++ мы должны будем добавлять материал в глобальное пространство имен с помощью ::?

Например, при использовании WinAPI, который находится на C, должен ли я сделать ::HANDLE вместо HANDLE и ::LoadLibrary вместо LoadLibrary? Что говорит С++ об этом? Это вообще хорошая идея, факторинг в вопросах, таких как читаемость и ремонтопригодность?

4b9b3361

Ответ 1

Поскольку пространства имен не существуют в C, не используйте:: HANDLE для доступа к типу HANDLE.

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

Кроме того, если вы находитесь в вложенном пространстве имен и объявляете свой собственный тип HANDLE (например), тогда компилятор будет использовать этот вместо windows.h one!

Таким образом, всегда предпочитайте использовать:: перед именами при работе в вложенном пространстве имен.

Ответ 2

Имена в С++ могут быть квалифицированными и неквалифицированными. Существуют различные правила для квалифицированного и неквалифицированного поиска имен. ::HANDLE - это квалифицированное имя, а HANDLE - неквалифицированное имя. Рассмотрим следующий пример:

#include <windows.h>

int main()
{
    int HANDLE;
    HANDLE x; //ERROR HANDLE IS NOT A TYPE
    ::HANDLE y; //OK, qualified name lookup finds the global HANDLE
}

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

Ответ 3

Основная интересность заключается в том, что различия с точки зрения компилятора, как уже было сказано, если вы включаете ::, то вы используете квалифицированный поиск, а не неквалифицированный поиск.

Преимущество использования квалифицированного поиска заключается в том, что он сможет точно определять конкретный символ. Недостатком является то, что он всегда будет определять этот конкретный символ --i.e. он отключит зависящий от аргумента поиск. ADL - большая и полезная часть языка, и, квалифицируя, вы эффективно отключите его, и это плохо.

Учтите, что в глобальном пространстве имен у вас была функция f, и вы добавили внутри T тип пространства N. Не считайте, что вы хотите добавить перегрузку f, которая примет аргумент T. Следуя принципу интерфейса, вы можете добавить f в пространство имен N, так как f - фактически операция, выполняемая на T, и она так же относится к типу. В этом случае, если у вас был код, который вызвал (рассмотрите общий код) ::f(obj) на объект неизвестного типа U, компилятор не сможет выбрать ::N::f(obj) как потенциальную перегрузку, поскольку код явно запрашивает перегрузка в глобальном пространстве имен.

Использование неквалифицированного поиска дает вам свободу определять функции, в которых они принадлежат, вместе с типами, которые используются в качестве аргументов. В то время как это не совсем то же самое, рассмотрите использование swap, если вы квалифицируете std::swap, тогда он не поднимет вашу ручную развертку void swap( T&, T& ) внутри вашего пространства имен N...

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

Ответ 4

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

Ответ 5

Обычно вам не нужно добавлять :: для глобального пространства имен. (Только в некоторых действительно редких случаях). IMHO вредит читабельности, но, с другой стороны, он, вероятно, не сломает ваш код

Ответ 6

Я поместил весь свой код в пространство имен, и я предпочитаю заголовки С++ над заголовками C, поэтому единственные символы, оставшиеся в глобальном пространстве имен, как правило, относятся к Windows API. Я избегаю вытягивать символы из других пространств имен в текущее пространство имен (например, у меня никогда не было using namespace std;), предпочитая вместо этого явно квалифицировать вещи. Это соответствует Руководству по стилю Google С++.

Поэтому я получил привычку отбирать вызовы функций WinAPI с помощью :: по нескольким причинам:

  • Последовательность

    . Для всего, что находится за пределами текущего пространства имен, я обращаюсь к нему явно (например, std::string), поэтому почему бы не ссылаться на Windows API явно (например, ::LoadLibraryW)? Пространство имен Windows API - это глобальное пространство имен.

  • Многие функции WinAPI называются в общем (например, DeleteObject). Если вы не знакомы с кодом, который вы читаете, вы можете не знать, является ли DeleteObject вызовом чего-то в текущем пространстве имен или в Windows API. Таким образом, я нахожу, что :: уточняет.

  • У многих фреймворков Windows есть методы с теми же именами, что и необработанные вызовы. Например, ATL::CWindow имеет метод GetClientRect со слегка отличной подписью, чем WinAPI GetClientRect. В этой структуре общий класс для вашего класса должен быть получен из ATL::CWindow, поэтому в вашей реализации класса нормально сказать GetClientRect вызывать унаследованный метод ATL и ::GetClientRect, если вам нужно вызвать функцию WinAPI. Это не является строго необходимым, так как компилятор найдет правильный, основанный на подписи. Тем не менее, я нахожу, что различие разъясняется читателю.

(Я знаю, что вопрос был не совсем о WinAPI, но пример был в терминах WinAPI.)

Ответ 7

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