C++:命名空间 - 如何正确使用头文件和源文件?

Dad*_*dyM 75 c++ namespaces header-files

考虑一对两个源文件:接口声明文件(*.h*.hpp)及其实现文件(*.cpp).

*.h文件如下所示:

namespace MyNamespace {
  class MyClass {
  public:
    int foo();
  };
}
Run Code Online (Sandbox Code Playgroud)

我在源文件中看到了两种不同的使用命名空间的做法:

*.cpp 练习#1:

#include "MyClass.h"
using namespace MyNamespace;

int MyClass::foo() { ... }
Run Code Online (Sandbox Code Playgroud)

*.cpp 练习#2:

#include "MyClass.h"
namespace MyNamespace {

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

}
Run Code Online (Sandbox Code Playgroud)

我的问题:这两种做法之间是否有任何差异,哪一种被认为比另一种更好?

Dan*_*n F 57

从代码可读性的角度来看,我认为使用#2方法可能更好:

您可以一次使用using多个名称空间,并且在该行下面编写的任何对象或函数都可以属于任何这些名称空间(禁止命名冲突).将整个文件包装在一个namespace块中更加明确,并允许您在.cpp文件中声明属于该命名空间的新函数和变量


Jam*_*nze 45

最明显的是您没有显示的选项:

int MyNamespace::MyClass::foo()
{
    //  ...
}
Run Code Online (Sandbox Code Playgroud)

它也非常冗长; 对大多数人来说太过分了.既然using namespace是名称冲突的接收,至少在我的经验中,应该避免,除非在非常有限的范围和地方,我通常使用你的#2.

  • 非常感谢.我们一起为命名空间用户创建了一个很好的FAQ页面.:) (2认同)
  • 伙计们,我真的不知道该选择谁。它们彼此互补时具有交集。 (2认同)

Joh*_*ane 8

这两种做法之间是否存在差异?

是.#1和#2分别是using-directivenamespace定义的示例.在这种情况下它们实际上是相同的但具有其他后果.例如,如果您同时引入新标识符MyClass::foo,则它将具有不同的范围:

#1:

using namespace MyNamespace;
int x;  // defines ::x
Run Code Online (Sandbox Code Playgroud)

#2:

namespace MyNamespace {
  int x;  // defines MyNamespace::x
}
Run Code Online (Sandbox Code Playgroud)

一个被认为比另一个更好?

#1优点:稍微简洁一点; 更难以在MyNamespace不知不觉中不小心引入一些东西.缺点:可能会无意中引入现有标识符.

#2优点:更清楚的是现有标识符的定义和新标识符的声明都属于MyNamespace.缺点:更容易无意中引入标识符MyNamespace.

对#1和#2的批评是,当你可能只关心成员的定义时,他们指的是整个命名空间MyNamespace::MyClass.这是严厉的,它很难传达意图.

#1的可能替代方法是using声明,其中仅包含您感兴趣的标识符:

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

int MyClass::foo() { ... }
Run Code Online (Sandbox Code Playgroud)


Jor*_*dan 5

我还想补充一点,如果您出于某种原因决定在 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(){}
Run Code Online (Sandbox Code Playgroud)

否则,如果您应用 #2 方法,这会很好。