在头文件和源文件(cpp)中创建C++命名空间

103

将头文件和cpp文件的内容都包含在命名空间中与仅包含头文件内容并在cpp文件中使用using namespace之间是否有区别?

所谓的区别是指可能会产生任何性能损失或略微不同的语义,可能会导致问题或我需要注意的任何事项。

例如:

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
namespace X
{
  void Foo::TheFunc()
  {
    return;
  }
}

VS

的翻译是“对比”。
// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
using namespace X;
{
  void Foo::TheFunc()
  {
    return;
  }
} 
如果没有区别,哪种形式更受欢迎,为什么?
9个回答

60

"namespace X"和"using namespace X"的区别在于,前者会将新声明放在命名空间下,而后者不会。

在您的示例中,没有新的声明-因此没有区别,因此没有首选方式。


这取决于项目和风格。通常模块中会有一个主要的命名空间用于一堆文件,并且第二个风格是有意义的。 - Nicholas Wilson

44

命名空间(Namespace)只是一种方法,用来改变函数签名,以避免冲突。有些人喜欢第一种方式,而有些人则喜欢第二种方式。这两种方式都不会对编译时性能产生任何影响。请注意,命名空间只是编译时的实体。

使用命名空间唯一会引起问题的情况是当我们拥有相同的嵌套命名空间名称时(即X::X::Foo)。这样做会增加混淆,不管是否使用关键字。


9

没有性能惩罚,因为结果是相同的,但是将你的Foo放入命名空间中会隐式地引入歧义,如果你在不同的命名空间中有Foo,你的代码可能会出错。我建议避免使用using来达到这个目的。

using namespace之后,你有一个杂项的{ ;-)


1
我不会把它叫做“迷失”,因为它与末尾的}匹配。但是,我会称那对大括号是多余的 ;) - blubberdiblub
1
@blubberdiblub,这个问题已经被编辑过了,如果你查看原始版本,你就会发现它是“走失”的;-) - Michael Krelin - hacker

3

如果您想从一个文件使用变量到另一个文件,我建议将其外部化,然后在源文件中进行初始化:

// [.hh]
namespace example
{
   extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
   int a, b, c;
}
// Then in the function below, you can init them as what you want: 
void reference
{
    example::a = 0;
}

1
如果第二个也能编译通过,那么就不应该有任何区别。命名空间在编译时处理,不应影响运行时操作。
但是从设计角度来看,第二个很糟糕。即使它能编译(不确定),它完全没有意义。

1
我认为它无法编译,但不是因为有差异,而是因为有一个杂项的 { 符号;-) - Michael Krelin - hacker
区别在于Foo::TheFunc()声明在全局命名空间中,而定义在X命名空间中。 - bert-jan

1

在 VS 情况下,Foo::TheFunc() 不在正确的命名空间中。使用 'void X::Foo::TheFunc() {}' 在正确的命名空间 (X) 中实现该函数。


这个问题有点老了,但是你知道这会带来什么后果吗?例如,他的VS案例在命名空间中声明函数,但在其外部定义,这样做会导致任何问题吗? - Adam Goodwin

1

如果您只包装.h文件,则必须在cpp文件中使用using namespace ...编写,否则每次都要使用有效的命名空间。通常情况下,您会同时包装.cpp和.h文件,否则您有可能使用来自另一个命名空间的对象,这可能会产生很多问题。


1

或者你可以这样做:

// asdf.h
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

那么

// asdf.cpp
#include "asdf.h"

void X::Foo::TheFunc()
{
  return;
}

0

我认为在这里做正确的事情是使用命名空间进行作用域限定。

namespace catagory
{
    enum status
    {
      none,
      active,
      paused
    }
};

void func()
{
    catagory::status status;
    status = category::active;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接