Рассмотрим пару из двух исходных файлов: файл объявления интерфейса ( *.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() { ... }
}
Мой вопрос: есть ли различия между этими двумя практиками и считается ли одна лучше другой?
c++
namespaces
header-files
Николай
источник
источник
int MyNamespace::MyClass::foo() ...
.Ответы:
С точки зрения читабельности кода, на мой взгляд, по этой причине, вероятно, лучше использовать метод №2:
У вас может быть
using
несколько пространств имен одновременно, и любой объект или функция, написанные под этой строкой, могут принадлежать любому из этих пространств имен (за исключением конфликтов имен). Обертывание всего файла вnamespace
блоке более явное и позволяет объявлять новые функции и переменные, которые принадлежат этому пространству имен, в файле .cpp.источник
Самым ясным является вариант, который вы не показали:
int MyNamespace::MyClass::foo() { // ... }
Это также очень многословно; слишком много для большинства людей. Поскольку
using namespace
это рецепт для конфликтов имен, по крайней мере, по моему опыту, и его следует избегать, за исключением очень ограниченных областей и мест, я обычно использую ваш № 2.источник
Да. # 1 и # 2 являются примерами директивы using и определения пространства имен соответственно. В этом случае они фактически одинаковы, но имеют другие последствия. Например, если вы введете рядом новый идентификатор
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 - это объявление-использование, которое включает только интересующий вас идентификатор:
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
источник
Я также хотел бы добавить, что если вы по какой-то причине решите реализовать специализацию шаблона в файле 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, все будет в порядке.
источник
Я хотел бы добавить еще один способ с использованием объявления-использования :
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
Это избавит вас от необходимости многократно вводить имя пространства имен, если у класса много функций.
источник