Вероятно, дубликат, но его нелегко найти ...
Учитывая заголовок вроде:
namespace ns1
{
class MyClass
{
void method();
};
}
Я видел method()
несколько способов определения в файле .cpp:
Версия 1:
namespace ns1
{
void MyClass::method()
{
...
}
}
Версия 2:
using namespace ns1;
void MyClass::method()
{
...
}
Версия 3:
void ns1::MyClass::method()
{
...
}
Есть ли «правильный» способ сделать это? Что-то из этого «неправильное» в том, что все они не означают одно и то же?
c++
coding-style
namespaces
Мистер мальчик
источник
источник
Ответы:
Версия 2 неясна и непроста для понимания, потому что вы не знаете, к какому пространству имен
MyClass
принадлежит, и это просто нелогично (функция класса не в том же пространстве имен?)Версия 1 верна, потому что она показывает, что в пространстве имен вы определяете функцию.
Версия 3 верна еще и потому, что вы использовали
::
оператор разрешения области видимости для ссылки наMyClass::method ()
в пространстве именns1
. Я предпочитаю версию 3.См. Пространства имен (C ++) . Это лучший способ сделать это.
источник
namespace N {struct X { void f(); }; X operator==( X const &, X const & ); }
, теперь в файле cpp с помощью оператора using вы можете определить функцию-член какvoid X::f() {}
, но если вы определите,X operator==(X const&, X const&)
вы будете определять другой оператор, отличный от определено в заголовке (вам нужно будет использовать там 1 или 3 для бесплатной функции).5 лет спустя, и я подумал, что упомяну об этом, что и выглядит красиво, и не является злом
источник
Я использую версию 4 (ниже), потому что она сочетает в себе большинство преимуществ версии 1 (краткость резонансного определения) и версии 3 (быть максимально явным). Главный недостаток в том, что люди не привыкли к нему, но, поскольку я считаю, что это технически лучше альтернатив, я не возражаю.
Версия 4: используйте полную квалификацию с использованием псевдонимов пространств имен:
В моем мире я часто использую псевдонимы пространств имен, поскольку все явно уточняется - если только это невозможно (например, имена переменных) или это известная точка настройки (например, swap () в шаблоне функции).
источник
outer
иinner
определяется как пространство имен в других файлах заголовков уже?Версия 3 делает связь между классом и пространством имен очень явной за счет большего количества типов. Версия 1 избегает этого, но фиксирует связь с блоком. Версия 2 имеет тенденцию скрывать это, поэтому я бы избегал этого.
источник
Руководство по стилю Googles C ++ диктует вашу версию 1, но без отступов.
источник
Я выбираю Num.3 (также известную как подробный вариант). Это больше похоже на набор текста, но намерение точно для вас и для компилятора. Проблема, которую вы разместили как есть, на самом деле проще, чем в реальном мире. В реальном мире существуют другие области для определений, а не только члены класса. Ваши определения не очень сложны только с классами - потому что их область действия никогда не открывается повторно (в отличие от пространств имен, глобальной области и т. Д.).
Num.1 это может потерпеть неудачу с областями, отличными от классов - все, что можно открыть повторно. Таким образом, вы можете объявить новую функцию в пространстве имен, используя этот подход, или ваши встроенные строки могут быть заменены через ODR. Это понадобится вам для некоторых определений (особенно для специализаций шаблонов).
Num.2 Это очень хрупко, особенно в больших базах кода - по мере изменения заголовков и зависимостей ваша программа не сможет компилироваться.
Num.3 Это идеальный вариант, но нужно много набирать - какова ваша цель - что-то определить . Это делает именно это, и компилятор подключается, чтобы убедиться, что вы не сделали ошибки, определение не рассинхронизировано с его объявлением и т. Д.
источник
Оказывается, дело не только в «стиле кодирования». Num. 2 приводит к ошибке связывания при определении и инициализации переменной, объявленной как extern в заголовочном файле. Взгляните на пример в моем вопросе. Определение константы в пространстве имен в файле cpp
источник
Все способы верны, и у каждого есть свои преимущества и недостатки.
В версии 1 у вас есть преимущество в том, что вам не нужно писать пространство имен перед каждой функцией. Недостатком является то, что вы получите скучную идентификацию, особенно если у вас более одного уровня пространств имен.
В версии 2 вы делаете свой код более чистым, но если у вас есть несколько пространств имен, реализованных в CPP, одно может напрямую обращаться к функциям и переменным другого, что делает ваше пространство имен бесполезным (для этого файла cpp).
В версии 3 вам придется печатать больше, и ваши функциональные строки могут быть больше, чем экран, что плохо для дизайнерских эффектов.
Есть и другой способ его использования. Он похож на первую версию, но без проблем с идентификацией.
Это вот так:
Вам решать, что лучше для каждой ситуации =]
источник
#ifdef
предложение.#define OPEN_NS(X)
я думаю, что это немного полезно, но не совсем ... Я не возражаю против макросов, но это похоже на OTT. Я думаю, что подход Дитмара Кюля лучше подходит для вложенных пространств имен.