C++标准在[basic.scope.hiding]中"same scope"到底意味着什么?

What the C++ standard exactly means by "same scope" in [basic.scope.hiding]?

本文关键字:scope same 意味着 什么 标准 basic C++ hiding      更新时间:2023-10-16

在C++14标准中,[basic.scope.hiding],第2段(3.3.10.2)说:

类名称或枚举名称可以通过变量、数据成员、,函数或在相同作用域中声明的枚举器。如果类或枚举名称与变量、数据成员、函数或枚举器在相同的作用域中以相同的名称声明(按任何顺序),则类或枚举名将隐藏在变量、数据员、函数或列举器名称可见的任何位置。

我对";"相同范围";。实际上,在下面的代码片段中,类C和变量C在同一范围内声明的情况是什么?

namespace case_1 {
int C;
class C;
// Here C refers to variable
}
namespace case_2 {
class C;
namespace nested {
int C;
// Here C refers to variable
}
}
namespace case_3 {
int C;
namespace nested {
class C;
// Here C refers to class
}
}
namespace case_4 {
enum Enum { A, B, C };
class C;
// Here C refers to enumerator
}

假设1:;"相同范围";是指";"相同块">

如果我们坚持这个假设,情况1应该受到规则3.3.10.2的关注。案例2呢?我想它包含在规则3.3.10.1:中

可以通过嵌套声明性区域或派生类中相同名称的显式声明来隐藏名称。

此外,这个假设很好地解释了情况3,其中类名隐藏了变量名(而不是相反的),但不能解释情况4。实际上,C枚举器是在与C类不同的块中声明的,但该类仍然是隐藏的。

假设2:;在相同范围内声明";是指";具有完全相同的范围">

如果这个假设是真的,那么我的代码中描述的任何情况都不受规则的影响,因为两个名字不可能有完全相同的范围。即使是case_1中的变量也具有与类不同的作用域。事实上,变量名的作用域在其声明之后开始,所以在类名之前。

假设3:;在相同范围内声明";是指";其中一个名称被声明在另一个"的范围内

如果该假设成立,则上述所有情况均应包含在规则3.3.10.2中。实际上,在case_1case_3中,C类是在C变量的范围内声明的;在case_2中,C变量是在C类的作用域中声明的;并且,在case_4中,C类是在C枚举器的作用域中声明的。然而,case_3不遵循规则,因为它是应该";获胜";并保持可见。

正如你所看到的,我的每一个假设都有一个缺点,我真的不明白标准中";"相同范围";在该段中。

类C和变量C在同一范围内声明的情况有哪些?

情况1和4属于同一范围。案例2和案例3的范围不相同。

在这种情况下,我确实无法在标准中找到"相同"的准确定义,但有意义的解释是比较每个声明的最小封闭范围(或者更确切地说,声明性区域1),并与测试结果相匹配。

假设1:"相同范围"意味着"相同区块">

虽然块有作用域,但它们并不等价。例如,还有命名空间作用域和类作用域。

,但无法解释情况4。事实上,C枚举器是在与C类不同的块中声明的,但该类仍然是隐藏的。

枚举声明没有作用域。枚举器和类在同一范围内。

假设2:"在同一范围内声明"意味着"具有完全相同的范围">

正如您所说,任何声明都不能与另一个声明具有完全相同的作用域,因此这种解释将使规则变得毫无意义。

假设3:"在同一范围内声明"意味着"其中一个名称在另一个的范围内声明。">

这不是正确的解释,因为嵌套的范围可以在一个声明的范围内,但就所讨论的规则而言,它不是同一个范围。


1在最新的标准草案中,措辞已被更改为使用术语"声明性区域",其含义显然与"范围"略有不同。不过,这并没有改变规则的本意。

这里,范围是指可见性
两个名称在同一范围内,当且仅当它们在某个地方同时为人所知(因此,如果它们相同,则会变得模糊/冲突)
我所说的"已知"是指您可以直接访问它们(如果名称相同,则使用完全相同的语法)。


事实上,C枚举器是在与C类不同的块中声明的,但该类仍然是隐藏的。

这是错误的
实际上enum并没有将其成员封装在本地作用域中。换句话说,enum成员与enum本身处于相同的范围内。

例如,如果我申报

enum MY_ENUM {A, B};

我可以通过My_ENUM::AMy_ENUM::B或者简单地通过AB来访问这些值。此外,允许隐式转换为int

如果要将值封装在MY_ENUM本地的作用域中(因此禁止AB进行访问),则必须将enum声明为enum class

enum class MY_ENUM {A, B};

但是,将不再允许隐式转换为int