【问题标题】:Nested NameSpaces in C++C++ 中的嵌套命名空间
【发布时间】:2011-03-13 01:33:37
【问题描述】:

当有嵌套的命名空间和对象声明时,我很困惑该怎么做。

我正在移植一些链接到具有一些命名空间的静态库的代码。

我所说的例子:

namespace ABC {

    namespace XYZ {

        //STUFF
    }
}

如何在代码中声明位于命名空间XYZ 中的对象?

如果我尝试:

XYZ::ClassA myobject;

或:

ABC::XYZ::ClassA myobject;

或:

ABC::ClassA myobject;

我明白了

没有命名类型

错误,即使ClassA 确实存在。

这里有什么合适的?

【问题讨论】:

  • 正确的方法是ABC::XYZ::ClassA。如果这不起作用,则问题出在其他地方。
  • 我想说 - 不要使用嵌套命名空间,让命名空间方案尽可能简单。
  • 你尝试的显然是正确的。也许您在真实代码中输错了命名空间/类?您也可以检查字符大小写(这是一个常见错误)。
  • 只是确保...您知道在嵌套名称空间中声明一个新类与在其中引用在外部库中声明的对象不同。
  • @Neil +1。将嵌套命名空间用于组织目的可能会导致比其价值更多的麻烦(ADL 相关以及语法负担)。我建议严格遵守它们以避免名称冲突并尽可能少地坚持。除非您在一个非常大的团队中工作,否则一个命名空间应该足以满足一个项目。

标签: c++ namespaces


【解决方案1】:

这取决于你已经使用的命名空间:

如果您不在命名空间或另一个不相关的命名空间中,则必须指定整个路径 ABC::XYZ::ClassA

如果你在ABC,你可以跳过ABC,直接写XYZ::ClassA

另外,值得一提的是,如果你想引用一个不在命名空间(或“根”命名空间)中的函数,你可以在它前面加上::

例子:

int foo() { return 1; }

namespace ABC
{
  double foo() { return 2.0; }

  void bar()
  {
    foo(); //calls the double version
    ::foo(); //calls the int version
  }
}

【讨论】:

    【解决方案2】:

    如果myobject 在该命名空间中声明并且您想再次声明它(用于定义它),您可以通过为其名称添加前缀而不是其类型来实现。

    ClassA ABC::XYZ::myobject;
    

    如果它的类型也在该命名空间中声明,您还需要在类型名称前加上前缀

    ABC::XYZ::ClassA ABC::XYZ::myobject;
    

    很少需要重新声明这样的对象。通常,对象的第一个声明也是它的定义。如果要首先声明对象,则必须在该名称空间中进行。下面声明并定义了“myobject”

    namespace ABC {
      namespace XYZ {
        ClassA myobject;
      }
    }
    

    如果您在这样的对象中定义,您可以通过说ABC::XYZ 来引用它。您不必为了在本地使用它而以某种方式“声明”该对象

    void f() {
      ABC::XYZ::myobject = someValue;
    
      // you *can* however use a using-declaration
      using ABC::XYZ::myobject;
      myobject = someValue;
    }
    

    【讨论】:

    • “对象的第一个声明往往也是它的定义”这似乎是错误的。如果您想在头文件中声明某个对象,则不应在其中定义它。否则,如果有 2 个 cpp 文件包含此头文件,我们将编译并尝试链接这些 cpp 文件,链接器将返回有关重复定义的错误。如果第二个代码 sn -p 即将在标头中,则应为namespace ABC{ namespace XYZ{ extern ClassA myobject;}},然后在相应的cpp文件中应为ClassA ABC::XYZ::myobject;(如果ClassA不在命名空间中)
    • @Number47 为什么会出错?我没有说“所有对象的声明都是定义”,你似乎认为我有。
    • @Johnnes 我没有说“在所有情况下都是错误的”。不过实话说。如果我们谈论的是namespace ABC {...} 之类的东西,那么我们很可能是在谈论头文件(我错了吗?)。但正如我所指出的,将ClassA myobject; 之类的内容放在标头中是一种不好的做法,因为它可能会导致链接器错误。所以在第 3 个 sn-p 中——对不起,在上一篇文章中它也应该是第 3 个——应该有 extern ClassA myobject; 或者应该有一个说明这个 sn-p 即将在 cpp 文件中使用,而不是在标题中。在其他方面,我们可能会误导我们的读者。 :)
    • @Number47 我不知道你是否错了(我没有对现有的编码指南进行调查),但我非常认为你错了。我的 cpp 文件也使用命名空间,而不是在定义该命名空间的实体时每次都重复明确限定名称,如果许多其他程序员也这样做,我不会感到惊讶。
    • 无论如何,多重定义的问题与这个问题完全正交。我也可以为我的最后一个 sn-p 写一个注释,并说“这个函数不应该放在头文件中,或者它应该是一个成员函数,因为它没有明确声明为内联”。 IMO 会是噪音。
    猜你喜欢
    • 1970-01-01
    • 2019-08-03
    • 2011-01-02
    • 1970-01-01
    • 2011-01-06
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 2021-10-26
    相关资源
    最近更新 更多