姓名查询说明
$10.2/4- "[ 注意:在以下位置查找姓名 详细类型说明符 (3.4.4) 或基说明符(第 10 条),对于 实例,忽略所有非类型 声明,同时查找名称 在嵌套名称说明符中 (3.4.3) 忽略函数、变量和 枚举器声明。”
在描述名称查找时,我发现此语句在本节中非常令人困惑。
void S(){}
struct S{
S(){cout << 1;}
void f(){}
static const int x = 0;
};
int main(){
struct S *p = new struct ::S; // here ::S refers to type
p->::S::f();
S::x; // base specifier, ignores the function declaration 'S'
::S(); // nested name specifier, ignores the struct declaration 'S'.
delete p;
}
我的问题:
我对规则的理解正确吗?
为什么执行 new 的行中的
::S
自动处理为 structS
,而在最后一行::S
表示函数 <全局命名空间中的 code>S这是否表明文档中存在歧义,还是我又要留下来了 。远离 C++ 标准文档?
$10.2/4- "[ Note: Looking up a name in
an elaborated-type-specifier (3.4.4)
or base-specifier (Clause 10), for
instance, ignores all nontype
declarations, while looking up a name
in a nested-name-specifier (3.4.3)
ignores function, variable, and
enumerator declarations."
I have found this statement to be very confusing in this section while describing about name lookup.
void S(){}
struct S{
S(){cout << 1;}
void f(){}
static const int x = 0;
};
int main(){
struct S *p = new struct ::S; // here ::S refers to type
p->::S::f();
S::x; // base specifier, ignores the function declaration 'S'
::S(); // nested name specifier, ignores the struct declaration 'S'.
delete p;
}
My questions:
Is my understanding of the rules correct?
Why
::S
on the line doing new treated automatically to mean structS
, whereas in the last line::S
means the functionsS
in the global namespace.Does this point to an ambiguity in the documentation, or is it yet another day for me to stay away from C++ Standard document?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问1:我想是的。
Q2:与 C 的兼容性。当您在 C 中声明
struct
时,标记名称就是标记名称。为了能够以独立的方式使用它,您需要一个typedef
。在 C++ 中,你不需要 typedef,这让生活变得更容易。但 C++ 规则由于需要能够导入现有的 C 标头而变得复杂,这些标头用函数名称“重载”了标记名称。典型的例子是 Unixstat()
函数,它使用struct stat*
作为参数。Q3:标准阅读通常是相当困难的……你需要知道没有其他地方可以修改你正在阅读的内容。知道如何做到这一点的人是语言律师,这并不奇怪......
Q1: I think so.
Q2: Compatibility with C. When you declare a
struct
in C, the tag name is just that, a tag name. To be able to use it in a standalone way, you need atypedef
. In C++ you don't need the typedef, that makes live easier. But C++ rules have been complicated by the need to be able to import already existing C headers which "overloaded" the tag name with a function name. The canonical example of that is the Unixstat()
function which uses astruct stat*
as argument.Q3: Standard reading is usually quite difficult... you need to already know that there is no place elsewhere modifying what you are reading. It isn't strange that people knowing how to do that are language lawyer...
您对第二条评论有误。在
S::x
中,S
是嵌套名称说明符中的名称。标准所指的“基本说明符”如下,您对此也不正确:
该代码调用该函数不是因为
::S 将是一个嵌套名称说明符(它不是一个嵌套名称说明符!),但因为如果函数和类/枚举都在同一范围内声明,则函数名称会隐藏类或枚举名称。
FWIW,以下代码对于 main 的第 2 行同样有效。
重要的是
S
位于::
之前,这使得查找忽略该函数。您将::
放在S
之前对您的情况没有任何影响。You are mistaken about the second comment. In
S::x
, theS
is a name in a nested name specifier. What the Standard refers to with "base-specifier" is the followingYou are also not correct about this:
That code calls the function not because
::S
would be a nested-name-specifier (it isn't a nested-name-specifier!), but because function names hide class or enumeration names if both the function and the class/enumeration are declared in the same scope.FWIW, the following code would be equally valid for line 2 of your main
What's important is that
S
preceedes a::
, which makes lookup ignore the function. That you put::
beforeS
has no effect in your case.