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

时间:2012-05-30 12:45:39

标签: c++ namespaces header-files

考虑一对两个源文件:接口声明文件(*.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() { ... }

}

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

5 个答案:

答案 0 :(得分:52)

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

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

答案 1 :(得分:43)

最清楚的是您没有显示的选项:

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

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

答案 2 :(得分:6)

  

这两种做法之间是否有任何差异

是。 #1和#2分别是using-directivenamespace definition的示例。在这种情况下它们实际上是相同的但具有其他后果。例如,如果您在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() { ... }

答案 3 :(得分: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方法,这将没问题。

答案 4 :(得分:0)

我想再添加一种方法,使用 using-declaration

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

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

这样,如果类有很多函数,这种方法可以避免多次输入命名空间名称