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

С++: Пространства имен - Как правильно использовать в заголовке и исходных файлах?

Рассмотрим пару двух исходных файлов: файл декларации интерфейса (*.h или *.hpp) и его файл реализации (*.cpp).

Пусть файл *.h выглядит следующим образом:

namespace MyNamespace {
  class MyClass {
  public:
    int foo();
  };
}

Я видел два разных метода использования пространств имен в исходных файлах:

*.cpp показывает практику № 1:

#include "MyClass.h"
using namespace MyNamespace;

int MyClass::foo() { ... }

*.cpp показывает практику № 2:

#include "MyClass.h"
namespace MyNamespace {

  int MyClass::foo() { ... }

}

Мой вопрос: Есть ли какие-то различия между этими двумя практиками и считается лучше других?

4b9b3361

Ответ 1

С точки зрения читаемости кода, вероятно, лучше, по-моему, использовать метод №2 по этой причине:

Вы можете быть using несколькими пространствами имен за раз, а любой объект или функция, написанные ниже этой строки, могут принадлежать любому из этих пространств имен (запрет конфликтов имен). Обтекание всего файла в блоке namespace более явственно и позволяет объявлять новые функции и переменные, которые принадлежат этому пространству имен в файле .cpp, а также

Ответ 2

Самый ясный вариант, который вы не показывали:

int MyNamespace::MyClass::foo()
{
    //  ...
}

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

Ответ 3

Существуют ли различия между этими двумя практиками

Да. # 1 и # 2 являются примерами using-directive и определение пространства имен соответственно. В этом случае они практически одинаковы, но имеют другие последствия. Например, если вы вводите новый идентификатор рядом с MyClass::foo, он будет иметь другую область:

# 1:

using namespace MyNamespace;
int x;  // defines ::x

# 2:

namespace MyNamespace {
  int x;  // defines MyNamespace::x
}

считается лучшим, чем другим?

# 1 Плюсы: немного более кратки; сложнее случайно ввести что-то в MyNamespace невольно. Минусы: непреднамеренно вытягивать существующие идентификаторы.

# 2 Плюсы: более ясно, что определения существующих идентификаторов и декларации новых идентификаторов принадлежат MyNamespace. Минусы: проще непреднамеренно ввести идентификаторы в MyNamespace.

Критика как # 1, так и # 2 состоит в том, что они относятся ко всему пространству имен, когда вы, вероятно, заботитесь только об определении членов MyNamespace::MyClass. Это тяжело, и он плохо сообщает о намерениях.

Возможной альтернативой # 1 является using-declaration, которая включает только интересующий вас идентификатор:

#include "MyClass.h"
using MyNamespace::MyClass;

int MyClass::foo() { ... }

Ответ 4

Я хотел бы также добавить, что если вы решите по какой-то причине реализовать специализированную специализацию в файле cpp и просто положитесь на using namespace, вы столкнетесь с следующей проблемой:

// .h file
namespace someNameSpace
{
  template<typename T>
    class Demo
    {
      void foo();
    };
}

// .cpp file
using namespace someNameSpace;

template<typename T>
void Demo<T>::foo(){}

// this will produce
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive]
template<>
void Demo<int>::foo(){}

В противном случае, если вы примените метод # 2, это будет нормально.

Ответ 5

Я хотел бы добавить еще один способ, используя using-declaration:

#include "MyClass.h"
using MyNamespace::MyClass;

int MyClass::foo() { ... }

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