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


88

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

}

我的问题是:这两种做法之间是否有差异,是否认为其中一种更好?


30
还有选项3:全名,例如int MyNamespace::MyClass::foo() ...
本杰明·班尼尔


@Dave不重复。这些问题是相辅相成的。建议将Dave提供的链接添加为“也请阅读...”。我的问题将帮助新手选择正确的样式。
nickolay 2012年

Answers:


62

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

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


戴夫(Dave)在他的评论中与您的问题相关的问题也概述了您正在寻找的两种方法之间的差异(如果有)的一些要点
Dan F

伙计们,我真的不知道该选择谁。它们在相辅相成的同时具有交集。
nickolay

只是发表评论以承认某些IDE(如CLion)仅在您使用选项/做法#2时才检测实现。
PedroTanaka 2015年

@PedroTanaka还是这样吗?我没有注意到任何此类问题。
John McFarlane'6

自从我发表评论以来,我还没有检查过@JMcF。在早期版本的Clion中,出现了问题。
PedroTanaka 2016年

51

最明显的是您未显示的选项:

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

它也很冗长;对大多数人来说太多了。由于using namespace至少在我的经验中,是避免名称冲突的原因,并且应该避免使用,除非在非常有限的范围和位置,我通常使用#2。


3
非常感谢。我们在一起为名称空间用户制作了一个很好的FAQ页面。:)
nickolay 2012年

2
伙计们,我真的不知道该选择谁。它们在相辅相成的同时具有交集。
nickolay

10

这两种做法之间有什么区别吗

是。#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的一种可能替代方法是using-声明,它仅包含您感兴趣的标识符:

#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方法,那就没问题了。


0

我想使用using-declaration添加另一种方法:

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

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

如果类具有许多功能,这种方法可以避免您多次键入名称空间名称

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.