【问题标题】:Member's potential scope for struct vs namespace结构与命名空间的成员的潜在范围
【发布时间】:2018-04-16 08:21:33
【问题描述】:

参考这段代码:

namespace Y {
  char f() { return y; } // error: y was not declared in this scope
  char y;
}

struct X {
  char  f() { return x; } // OK
  char  x;
};

根据basic.scope.namespace#1

命名空间定义的声明区域是它的 命名空间主体。在命名空间主体中声明的实体被称为 命名空间的成员,以及这些声明引入的名称 进入命名空间的声明区域被称为成员 命名空间的名称。它的潜在范围包括从名称声明点开始的命名空间。

问题

  1. 说错误是由于Y::y 尚未在Y::f() 中声明是否正确?

  2. 我不明白为什么namespace 成员在声明期间没有“reodering”,而struct 有。禁止这种行为的原因可能是什么? 标准是否有类似的规定?

【问题讨论】:

  • 声明通常必须在使用之前,在类成员函数内联实现中使用类成员是一个罕见的例外

标签: c++ scope namespaces declaration


【解决方案1】:

说错误是由于Y::y 尚未在Y::f() 中声明是正确的吗?

是的。

我不明白为什么在声明期间没有对命名空间成员进行“重新排序”,而对于 struct 却有。禁止这种行为的原因可能是什么?标准是否有类似的规定?

与类相比,命名空间的最大障碍是它们永远不会“关闭”。您始终可以通过在另一个翻译单元中重新打开命名空间并在其中声明更多内容来将成员添加到命名空间。然而,一个类声明,对于它的所有成员,必须完全出现在一个翻译单元中。以后也不会再添加了。

[class.mem]/1

类定义中的成员规范声明了完整的集合 班级成员;不能在别处添加成员。

命名空间的问题是棘手的。但是类只需要更多的、相当本地化的工作。

因此,对于语言设计者和编译器编写者来说,要求命名空间声明在使用之前出现要容易得多。

您还应该注意,您只能在定义中的一组特定位置使用该类的其他成员。

[class.mem]/6

一个类被认为是一个完全定义的对象类型([basic.types]) (或完整类型)在 class-specifier 的结束 }。内 class member-specification,该类被认为是完整的 函数体、默认参数、noexcept 说明符和默认值 成员初始化器(包括嵌套类中的此类内容)。 否则,它在自己的类中被认为是不完整的 成员规范

【讨论】:

    【解决方案2】:

    您错误地认为结构存在“重新排序”。

    考虑以下结构定义。

    #include <iostream>
    
    struct A
    {
        char s[N];
        enum { N = 10 };
    };
    
    int main() 
    {
        return 0;
    }
    

    编译器将发出错误,因为名称N 在数组声明中使用时尚未声明。因此,类范围内都不存在“重新排序”。至于成员函数,则首先在类范围内搜索成员函数中使用的名称。

    此外,在命名空间中声明的名称可以隐藏在外部命名空间中声明的相同名称。结果,“重新排序”打破了变量的范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-29
      • 2012-05-03
      相关资源
      最近更新 更多