Возможно, дубликат, но не простой поиск...
Учитывая заголовок как:
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()
{
...
}
Есть ли "правильный" способ сделать это? Являются ли какие-либо из этих "неправильных" тем, что они не все означают одно и то же?
Ответ 1
Версия 2 неясна и не понятна, потому что вы не знаете, к какому пространству имен MyClass
принадлежит, и это просто нелогично (функция класса не в том же пространстве имен?)
Версия 1 правильная, потому что она показывает, что в пространстве имен вы определяете функцию.
Версия 3 правильна также потому, что вы использовали оператор разрешения области ::
для ссылки на MyClass::method ()
в пространстве имен ns1
. Я предпочитаю версию 3.
См. Пространства имен (С++). Это лучший способ сделать это.
Ответ 2
Я использую версию 4 (см. ниже), потому что она сочетает в себе большинство преимуществ версии 1 (кратности ресоэффективного определения) и версии 3 (максимально явная). Основным недостатком является то, что люди не привыкли к этому, но поскольку я считаю его технически превосходящим альтернативы, я не против.
Версия 4: используйте полную квалификацию с использованием псевдонимов пространства имен:
#include "my-header.hpp"
namespace OI = outer::inner;
void OI::Obj::method() {
...
}
В моем мире я часто использую псевдонимы пространства имен, поскольку все явно квалифицировано - если оно не может (например, имена переменных) или оно является известной точкой настройки (например, swap() в шаблоне функции).
Ответ 3
5 лет спустя, и я подумал, что упомянул об этом, который оба выглядит красивым и не злым.
using ns1::MyClass;
void MyClass::method()
{
// ...
}
Ответ 4
Версия 3 делает связь между классом и пространством имен очень явным за счет большей типизации. Версия 1 избегает этого, но фиксирует связь с блоком. Версия 2 имеет тенденцию скрывать это, поэтому я бы избегал этого.
Ответ 5
Оказывается, это не только "предмет в стиле кодирования". Num. 2 приводит к ошибке связывания при определении и инициализации объявленной переменной extern в файле заголовка. Взгляните на пример в моем вопросе. Определение константы в пространстве имен в файле cpp
Ответ 6
Все способы правильные, и каждый из них имеет свои преимущества и недостатки.
В версии 1 у вас есть преимущество в том, что вам не нужно писать пространство имен перед каждой функцией. Недостатком является то, что вы получите скучную идентификацию, особенно если у вас более одного уровня пространств имен.
В версии 2 вы делаете свой код более чистым, но если в CPP реализовано более одного пространства имен, можно напрямую обращаться к другим функциям и переменным, что делает ваше пространство имен бесполезным (для этого файла cpp).
В версии 3 вам нужно будет ввести больше, а ваши функциональные строки могут быть больше, чем экран, что плохо для дизайнерских эффектов.
Существует и другой способ использования некоторыми людьми. Это похоже на первую версию, но без проблем идентификации.
Это так:
#define OPEN_NS1 namespace ns1 {
#define CLOSE_NS1 }
OPEN_NS1
void MyClass::method()
{
...
}
CLOSE_NS1
Вам решать, какой из них лучше для каждой ситуации =]
Ответ 7
Я выбираю Num.3 (a.k.a. verbose version). Это больше печатает, но намерение точно для вас и для компилятора. Проблема, которую вы разместили как есть, на самом деле проще, чем реальный мир. В реальном мире существуют другие области определения, а не только члены класса. Ваши определения не очень сложны только для классов - потому что их область никогда не открывается (в отличие от пространств имен, глобальной области видимости и т.д.).
Num.1 это может завершиться неудачно с областями, отличными от классов, - все, что может быть вновь открыто. Таким образом, вы можете объявить новую функцию в пространстве имен, используя этот подход, или ваши встроенные строки могут быть заменены через ODR. Вам понадобится это для некоторых определений (в частности, специализированных шаблонов).
Num.2 Это очень хрупко, особенно в больших кодовых базах - при смещении заголовков и зависимостей ваша программа не сможет скомпилироваться.
Num.3 Это идеальное, но многого типа - то, что вы намерены определить. Это делает именно это, и компилятор запускается, чтобы убедиться, что вы не допустили ошибку, определение не синхронизируется с его объявлением и т.д.
Ответ 8
Руководство по стилю Google С++ Googles определяет вашу версию 1 без отступов.
![Googles C++ Style Guide for namespaces]()