奇怪的C++成员函数指针的规则?
可能的重复:
带括号的成员函数地址错误
在 这个最近的问题OP遇到了C++语言的一个奇怪的规定,使得如果成员函数名称带有括号,则获取该成员函数的地址是非法的。例如,这段代码是非法的:
struct X {
void foo();
};
int main() {
void (X::* ptr)();
ptr = &(X::foo); // Illegal; must be &X::foo
}
我查了一下,发现这是由于 C++ ISO 规范的 §5.3.1/3 造成的,其中内容如下
仅当显式 & 时才会形成指向成员的指针。使用且其操作数是未括在括号中的限定 ID [...]
有谁知道为什么规范有这个规则吗?它特定于指向成员的指针,因此我怀疑这会解决一些语法上的歧义,但老实说,我根本不知道它可能是什么。
Possible Duplicate:
Error with address of parenthesized member function
In this recent question the OP ran into a strange provision of the C++ language that makes it illegal to take the address of a member function if that member function name is parenthesized. For example, this code is illegal:
struct X {
void foo();
};
int main() {
void (X::* ptr)();
ptr = &(X::foo); // Illegal; must be &X::foo
}
I looked this up and found that it's due to §5.3.1/3 of the C++ ISO spec, which reads
A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses [...]
Does anyone have any idea why the spec has this rule? It's specific to pointers-to-member, so I would suspect that there is some grammatical ambiguity that this resolves, but I honestly haven't the faintest idea what it might be.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这只是个人意见。
如果允许
&(qualified-id)
作为&(unary-expression)
,qualified-id 必须是一个表达式,并且表达式应该有一个类型
(即使它不完整)。
然而,C++ 没有表示成员的类型,只有
指向成员的指针。
例如,以下代码无法编译。
为了使
&(qualified-id)
有效,编译器必须保存内部成员类型。
但是,如果我们放弃
&(qualified-id)
表示法,编译器就不需要处理成员类型。
由于成员类型始终以指向它的指针的形式处理,
我猜标准优先考虑简化编译器的类型
系统一点。
This is just a personal opinion.
If
&(qualified-id)
is allowed as&(unary-expression)
,qualified-id has to be an expression, and an expression is expected to have a type
(even if it is incomplete).
However, C++ didn't have a type which denotes a member, had only
a pointer to member.
For example, the following code cannot be compiled.
In order to make
&(qualified-id)
be valid, the compiler has to holda member type internally.
However, if we abandon
&(qualified-id)
notation, the compiler doesn't needto handle member type.
As member type was always handled in the form of a pointer to it,
I guess the standard gave priority to simplify the compiler's type
system a little.
想象一下这段代码:
如果没有括号的技巧,您将无法直接获取 B 的数据成员的指针(您将需要基类转换和带有
this
的游戏 - 不太好)。来自ARM:
IS 只是保留了这个标准之前的概念,并明确提到括号使它这样你就不会没有得到指向成员的指针。
Imagine this code:
Without the trick with the parentheses, you would not be able to take a pointer directly to B's data member (you would need base-class casts and games with
this
- not nice).From the ARM:
The IS just kept this pre-Standard concept and explicitly mentioned that parentheses make it so that you don't get a pointer to member.