为什么头文件中需要命名空间?

时间:2013-02-26 13:35:08

标签: c++ interface namespaces header-files

我熟悉命名空间的以下用法。

在头文件中(例如people.h),我描述了名称空间的接口。例如:

namespace people{
   int getAge(str Name);
   void setName(str Name);
}

然后在people.cpp中我从空间名称中定义方法:

#include "people.h"
int people::getAge(str Name) {
   something_1;
   something_2;
}

void people::setName(str Name) {
   something_1;
}

但是,在我所拥有的头文件中,我看到除namespace people之外还有其他命名空间的接口(例如namespace dogs)。并且这些名称空间未在people.cpp文件中定义。

所以,我认为(由于一些奇怪的原因)namespace dogs的接口被放入people.h,然后名称空间狗在"狗中定义。 CPP"文件。因此,换句话说,我假设在两个不同的cpp文件中定义了两个不同的名称空间,但它们的接口在一个头文件中描述。然而,这个假设似乎是错误的,因为我发现有许多头文件声明"命名空间狗"。

所以,我假设2people.h中的namespace dogs"文件有另一个功能,但我无法弄清楚它是什么功能。有人可以帮帮我吗?

ADDED

我试图理解的代码不是由我编写的,而且工作正常。所以,它应该是有道理的。可能是我不够清楚。所以,我试着举个例子:

在头文件(people.h)中,我有:

namespace etet
{
    class date;
}

namespace xsystem{
    class estimation_module;
}

namespace people {
   a_lot_of_different_stuff;
}

然后people.cpp定义了属于人名空间的所有方法。

2 个答案:

答案 0 :(得分:2)

您会混淆名称空间和类。通常,类定义出现在头文件(.h)中,其成员函数的实现出现在相应的实现文件(.cpp)中。

命名空间与class的工作方式不同。如果在多个翻译单元中定义class,则它们必须在所有翻译单元中具有完全相同的标记。您甚至无法重新排序成员,即使它会导致完全相同的类。通过使用上述头文件很容易满足此要求。每个需要课程foo的翻译单元都包含foo.h的内容,因为他们在需要时会#include "foo.h"。当然,它们都包含与foo完全相同的定义,因为它们都包括foo.h

但是,这与命名空间非常不同。命名空间可以在相同和不同的翻译单元中多次引入,而不是每次都是相同的标记。这样的事情完全没问题:

namespace bar {
  void baz();
  struct x;
}
// some stuff
namespace bar {
  void do_something(x);
}

namespace bar的每次出现都会向该命名空间引入一些声明。

您通常会在同一名称空间中定义许多类。这些类的每个头都将执行namespace whatever { ... }并将类定义引入该命名空间。

有时您甚至希望在单个头文件中向多个名称空间或嵌套名称空间引入内容。没有什么可以阻止你这样做。这样做的一种可能情况是,如果要转发从另一个命名空间声明某些内容。假设您在people.h中定义了一个类,如此:

namespace people {
  class person {
    dogs::dog* pet_dog;
  };
}

现在,这个class需要知道dog命名空间中的dogs类型。做他的一种方法是#include "dogs.h"。但是,由于pet_dog只是一个指针,我们可以使用不完整的类型,因此我们可以像这样转发声明dog

namespace dogs {
  class dog;
}

namespace people {
  class person {
    dogs::dog* pet_dog;
  };
}

答案 1 :(得分:2)

“命名空间界面”是一种误导性的概念。命名空间只是一个名字组合在一起的名字(就像你和你的兄弟姐妹一样)。它没有“ interface ”,因为没有命名空间“ obejct ”。

#include "people.h"
int people::getAge(str Name) {
   something_1;
   something_2;
}

void people::setName(str Name) {
   something_1;
}

完全等同于

#include "people.h"
namespace people
{
  int getAge(str Name) {
     something_1;
     something_2;
  }

  void setName(str Name) {
     something_1;
  }
}

可能是这个比较熟悉,也可能不是。 头部声明函数不存在于cpp中的事实,只是意味着它们可能存在于另一个中。

关于namespace name { ..... }声明可以在许多文件中重复的事实,每个包含各种函数都是完全正常的,因为namespace关键字没有声明对象。它只是组名。事实上 - 说“命名”命名空间是一种常见的语言滥用。声明的是名称空间的名称。

在不同地方声明的不同名称可以属于同一个组。那里没有什么神秘的东西。

你的词汇让我觉得你在namespace es和class s

中混淆struct

<强>增加:

在您澄清之后,a_lot_of_different_stuff包含使用etet::datexsystem::estimation_module;

的声明

编译器必须知道这个名称(并且只有名称),但是标题不能递归地包含各自的标题,因为它们很可能已经包含people.h

典型的“curculare reference”问题,如here,但涉及不同的命名空间。