Правильный способ определения методов пространства имен C++.файл cpp


вероятно, дубликат, но не простой для поиска...

данный заголовок как:

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()
{
 ...
}

есть ли "правильный" способ сделать это? Есть ли среди них "неправильность" в том, что они не означают одно и то же?

8 85

8 ответов:

Версия 2 непонятно и не легко понять, потому что вы не знаете, какое пространство имен MyClass принадлежит и это просто нелогично (функция класса не в том же пространстве имен?)

Версия 1 права, потому что она показывает, что в пространстве имен вы определяете функцию.

версия 3 является правильным также потому, что вы использовали :: оператор разрешения области для ссылки на MyClass::method () в пространстве имен ns1. Я предпочитаю вариант 3.

посмотреть Пространства Имен (C++). Это лучший способ сделать это.

5 лет спустя, и я подумал, что упомяну об этом, что выглядит красиво и не является злом

using ns1::MyClass;

void MyClass::method()
{
  // ...
}

Я использую версию 4 (ниже), потому что она сочетает в себе большинство преимуществ версии 1 (краткость резоективного определения) и версии 3 (быть максимально явным). Главным недостатком является то, что люди не привыкли к нему, но поскольку я считаю, что он технически превосходит альтернативы, я не возражаю.

версия 4: используйте полную квалификацию, используя псевдонимы пространства имен:

#include "my-header.hpp"
namespace OI = outer::inner;
void OI::Obj::method() {
    ...
}

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

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

оказывается, это не только "дело стиля кодирования". Номер. 2 приводит к ошибке связывания при определении и инициализации переменной, объявленной extern в заголовочном файле. Взгляните на пример в моем вопросе. определение константы в пространстве имен в cpp-файле

все стороны правы, и каждый из них имеет свои преимущества и недостатки.

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

в версии 2 Вы делаете свой код чище, но если у вас есть более одного пространства имен, реализуемого в CPP, один может получить доступ к функциям другого и переменные напрямую, что делает ваше пространство имен бесполезным (для этого файла cpp).

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

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

это так:

#define OPEN_NS1 namespace ns1 { 
#define CLOSE_NS1 }

OPEN_NS1

void MyClass::method()
{
...
}

CLOSE_NS1

это до вас, чтобы выбрать, какой из них лучше для каждой ситуации =]

Руководство По Стилю Googles C++ диктует свою версию 1, без отступа, хотя.

Googles C++ Style Guide for namespaces

Я выбираю Num.3 (а.к.а. подробного версия). Это больше типизация, но намерение точно для вас и для компилятора. Проблема, которую вы разместили как есть, на самом деле проще, чем в реальном мире. В реальном мире существуют другие области для определений, а не только члены класса. Ваши определения не очень сложны только с классами-потому что их область никогда не открывается (в отличие от пространств имен, глобальной области и т. д.).

Num.1 это может не сработать с областями других классов - ничего это можно снова открыть. Таким образом, вы можете объявить новую функцию в пространстве имен, используя этот подход, или ваши строки могут быть заменены через ODR. Это потребуется для некоторых определений (в частности, для специализации шаблонов).

Num.2 это очень хрупко, особенно в больших кодовых базах - по мере сдвига заголовков и зависимостей ваша программа не сможет компилироваться.

Num.3 это идеально, но много, чтобы напечатать-что ваше намерение состоит в том, чтобы определить что-то. Этот делает именно это, и компилятор запускает, чтобы убедиться, что вы не ошиблись, определение не синхронизировано с его объявлением и т. д..