为什么每个人都使用unanchored名称空间声明(即std :: not :: std::)?

时间:2009-11-02 15:23:08

标签: c++ namespaces

在我看来,使用未锚定的命名空间只是在有人放入一个新的命名空间时会遇到麻烦,这个命名空间恰好与根级命名空间同名并且神秘地改变了很多程序的含义。那么,为什么人们总是说std::而不是::std::。他们真的是说“我想使用任何std方便,而不是根本。”?

这是我的意思的一个例子:

在fred / Foo.h中:

#include <string>

namespace fred {

class Foo {
 public:
   void aPublicMember(const std::string &s);
};

} // end namespace fred

在fred / Bar.h中:

namespace fred {
namespace std {  // A standard fred component

class string { // Something rather unlike the ::std::string
   // ...
};

} // namespace std

class Bar {
 public:
   void aPublicMember(std::string &s);
};

} // namespace fred

在oops.cpp中:

#include <string>
#include "fred/Bar.h"
#include "fred/Foo.h"  // Oops, the meaning of Foo is now different.

这是人们想要的,还是我错过了什么?

也许你说你应该永远不要命名空间std。这一切都很好,但那么其他一些根级命名空间呢?任何人在任何地方定义的任何根级别命名空间是否总是对子命名空间名称是禁止的?

为了澄清,我不会考虑任何回答,告诉我std是特别的,因为我只是以它为例。我说的是一个普遍的问题,我用std作为道具来说明它,虽然我承认这是一个相当惊人的道具。

8 个答案:

答案 0 :(得分:35)

  

那么,为什么人们总是说std​​ ::   而不是:: std ::

可能是因为它们从来没有真正出现歧义问题。

沿着同样的路线:我从来没有在地址中加入“地球”,我不会这样做。

你必须在某处绘制线,这是一个合理的假设,其他人不会创建自己的std命名空间,或者至少那个不会非常受欢迎的库。 :)

答案 1 :(得分:18)

非锚定命名空间的实际原因是一级命名空间通常就足够了。如果不是,通常会将第二级用于实现细节。最后,即使使用多个级别,它们仍然通常从根级别隐式指定。即。即使在命名空间ns1内,您通常也会引用ns1::ns2::foo而不是ns2::foo::ns1::ns2::foo

因此,出于这三个原因,::ns1形式在正常情况下是多余的。我认为这是Boost提交的唯一案例,因为作为Boost作者,我不知道我的软件将在何处使用。

答案 2 :(得分:7)

  

为什么人们总是说std​​ ::

并非总是如此。我使用stringusing ::std::string。如果有fred::std::string那么没什么不好的,因为我仍然使用std::string。在小型cpp文件中,它甚至可以是using namespace ::std。样品:

#include <iostream>
using ::std::string;
//using namespace ::std; // good for small cpp-files

int main()
{
  string s = "sometext"; // no leading ::std
}
  

你应该永远不要命名命名空间std

是的,您不应该为自定义命名空间命名std

答案 3 :(得分:3)

这非常人为:

namespace fred {
namespace std {  // A standard fred component

class string { // Something rather unlike the ::std::string
   // ...
};

} // namespace std
} // namespace fred

这个弗雷德无法解释为什么他会对整个团队这样做。

回答你的问题:人们首先省略“::”因为这是一种习惯,这节省了时间,因为更容易预期在任何地方使用命名空间时,这样的名称是绝对的,而不是相对的。

答案 4 :(得分:3)

好的,你说std只是一个例子。但对我来说,似乎你的问题只适用于某人做一些像覆盖std一样邪恶的事情。

让我举一个例子:

namespace logging
{
    // Logs to local file
}

namespace server
{
    namespace logging
    {
        // Logs to remote destination
    }
}

namespace client
{
    namespace logging
    {
        // Logs to local file and to screen
    }
}

在这种情况下,不预先::会导致默认行为。

答案 5 :(得分:2)

std的情况下,我不会假设任何其他具有相同名称,相同类但含义不同的命名空间。

在其他情况下,领先的::看起来很丑陋,并且使阅读代码更加困难(在我看来)。命名空间冲突太少,无法将::放在所有内容之前。

答案 6 :(得分:2)

许多代码都是在全局命名空间中编写的。如果有人真的重新定义了:: std ::,那么在这种代码中如何引用它就无所谓了。

此外,您的方案既不可能也不容易解决。首先,因为有'std'的惯例是你不使用那个名字。其次,如果您遇到定义'std'命名空间的包,您只需执行此操作:

#include <package_name.hpp>

namespace package_name {
  using namespace std;
}

namespace my_app {
  class my_class : public package_name::class_of_something {};
}

或类似的东西。您可能必须将:: std明确命名为std。我的观点是:人们一直在使用未锚定的'std ::',因为即使是最坏情况的后果也不是什么大问题,而且不太可能。

答案 7 :(得分:1)

与保留前缀为_的名称的方式相同,请将std::视为保留。