【问题标题】:How does the namespace scope works in C++?命名空间范围在 C++ 中如何工作?
【发布时间】:2021-10-17 01:32:42
【问题描述】:

C++ ISO 草案 2020(6.4.6 Namespace Scope) 在第一段中引用(由我加粗):

命名空间定义的声明区域是它的命名空间主体 .在命名空间主体中声明的实体被称为 命名空间,以及由这些声明引入的名称 命名空间的声明区域被称为 命名空间。命名空间成员名称具有命名空间范围。 它的潜力 范围从名称的声明点包括其命名空间 (6.4.2) 起;并且对于每个提名的使用指令(9.8.3) 成员的命名空间,成员的潜在范围包括 使用指令的潜在范围的一部分 成员的声明点。

我以为未命名和命名命名空间没有区别,但是下面的代码有问题:

#include <iostream>
namespace A {int a = 1;}
namespace {int b = 1;}
void main() {
    std::cout << a; // identifier "a" is undefined
    std::cout << b;
}

Cppreference 给出了这个问题的原因:

在未命名的命名空间或在 内联命名空间包括该名称可能具有的潜在范围 如果它是在封闭的命名空间中声明的。

但是根据我对这个问题的第一句话的理解,这个错误不应该发生。这里发生了什么?

【问题讨论】:

  • namespace { /*body*/ } 的行为,by definition,与namespace UniqueName {} using namespace UniqueName; namespace UniqueName { /*body*/ } 一样,其中UniqueName 是翻译单元独有的一些发明标识符。您的示例中两个命名空间之间的区别在于这个隐含的 using 指令。
  • 如果在您的示例中 a 可以通过不合格的查找找到,而不指定其命名空间,那么命名空间将毫无意义。为什么你认为错误不应该发生?你是如何从你引用的段落得出这个结论的?
  • @IgorTandetnik 我认为问题在于我对“向前”一词的解释。我把它理解为从声明点开始,直到(好吧,直到一切)到翻译单元的结尾,但接下来是直到命名空间主体的结尾,对吧?
  • “从声明开始就包含 其命名空间”。不是整个源文件,而是位于它所属的名称空间内的部分。 “命名空间主体的结尾”没有明确定义,因为命名空间可能是零散定义的:namespace N { int x;} namespace N {int y;}
  • 在未命名的命名空间中声明的名称在封闭的命名空间中可见的原因是前面提到的隐式 using 指令。所以你引用的另一部分开始发挥作用:“对于每个指定成员命名空间的使用指令(9.8.3),成员的潜在范围包括使用指令的潜在范围的那部分......”

标签: c++ namespaces language-lawyer


【解决方案1】:

我认为未命名和命名命名空间之间没有区别

ab 均在 main 中可用。但是如果没有范围解析,就无法访​​问a。文档中提到“潜在范围”、“实际范围”和“范围”,加上块/类/函数/命名空间范围,可能会让人感到困惑。

您可以使用此代码查看已命名和未命名namespace 的相似性:

class foo
{
    std::string str;
public:
    foo(const char* s) { str = s; cout << str << " foo()\n"; }
    ~foo() { cout << str << " ~foo()\n"; }
};

namespace named { foo a("named"); }
namespace { foo b("unnamed"); }
int main()
{
    cout << "start\n";
    named::a;
    b;
    cout << "end\n";
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    相关资源
    最近更新 更多