指针到成员的混淆 [英] Pointer-to-member confusion
问题描述
我想要了解这个程式中错误的一致性:
#include< iostream> ;
class A {
public:
void test();
int x = 10;
};
void A :: test(){
std :: cout< x < std :: endl; //(1)
std :: cout<< A :: x< std :: endl; //(2)
int * p =& x;
// int * q =& A :: x; //错误:无法将初始化中的'int A :: *'转换为'int *' //(3)
}
int main(){
const int A :: * a =& A ::X; //(4)
A b;
b.test();
}
输出 10 10
。我标记了程序的4分,但(3)是我最大的问题:
-
x
是从成员函数内部正常提取的。 -
x
c>返回对象x
。 -
int
lvalue(2)中,为什么& A :: x
int * ,而是返回int A :: *
?范围操作符甚至优先于&
运算符,因此应首先运行A :: x
code> int lvalue。即这应该与&(A :: x)
相同? (添加括号确实工作顺便)。 - 这里有点不同,当然,scope运算符引用一个类成员,但没有引用的对象。
那么为什么 A :: x
对象 x
,而是返回成员的地址,忽略 ::
之前 ;
C ++标准没有明确指定运算符优先级; 可以从语法规则中隐含地推导出运算符优先级,但是这种方法不能理解偶尔的特殊情况,例如不适合运算符优先级的传统模型。
[expr.unary.op] / 3:
一元
&
运算符是指向其操作数的指针。操作数应为左值或 qualified-id 。如果操作数是
qualified-id 命名某个类的非静态或变体成员
,结果具有指向类m
类型T
的CC
类型
T
',并且是指定C :: m
的prvalue。否则,如果表达式的类型是T
,结果具有类型指向T
',并且是prvalue即指定对象的地址或指向指定函数的指针。
/ 4:
指向成员的指针仅在使用显式
&
时形成,其操作数为 -id 未括在括号中。 [注意:
也就是表达式&(qualified-id)
,其中 qualified-id 括在圆括号中,不会形成类型为指向成员的指针的表达式。
[expr.prim.general] / 9:
一个 nested-name-specifier ,表示一个类, c $ c> template ,然后是该类或其基类的成员的名称是 qualified-id
。
它是一个表达式& A :: x
A
如果 x $>的成员
x
c $ c>是非联合类 A
的非静态成员,并且运算符优先级对此没有影响。
I'm trying to understand the consistency in the error that is thrown in this program:
#include <iostream>
class A{
public:
void test();
int x = 10;
};
void A::test(){
std::cout << x << std::endl; //(1)
std::cout << A::x << std::endl; //(2)
int* p = &x;
//int* q = &A::x; //error: cannot convert 'int A::*' to 'int*' in initialization| //(3)
}
int main(){
const int A::* a = &A::x; //(4)
A b;
b.test();
}
The output is 10 10
. I labelled 4 points of the program, but (3) is my biggest concern:
x
is fetched normally from inside a member function.x
of the object is fetched using the scope operator and an lvalue to the objectx
is returned.- Given
A::x
returned anint
lvalue in (2), why then does&A::x
return notint*
but instead returnsint A::*
? The scope operator even takes precedence before the&
operator soA::x
should be run first, returning anint
lvalue, before the address is taken. i.e. this should be the same as&(A::x)
surely? (Adding parentheses does actually work by the way). - A little different here of course, the scope operator referring to a class member but with no object to which is refers.
So why exactly does A::x
not return the address of the object x
but instead returns the address of the member, ignoring precedence of ::
before &
?
The C++ standard doesn't explicitly specify operator precedence; it's possible to deduce operator precedence implicitly from the grammar rules, but this approach fails to appreciate the occasional special case like this which doesn't fit into a traditional model of operator precedence.
[expr.unary.op]/3:
The result of the unary
&
operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant memberm
of some classC
with typeT
, the result has type 'pointer to member of classC
of typeT
' and is a prvalue designatingC::m
. Otherwise, if the type of the expression isT
, the result has type 'pointer toT
' and is a prvalue that is the address of the designated object or a pointer to the designated function.
/4:
A pointer to member is only formed when an explicit
&
is used and its operand is a qualified-id not enclosed in parentheses. [ Note: that is, the expression&(qualified-id)
, where the qualified-id is enclosed in parentheses, does not form an expression of type 'pointer to member'.
[expr.prim.general]/9:
A nested-name-specifier that denotes a class, optionally followed by the keyword
template
, and then followed by the name of a member of either that class or one of its base classes, is a qualified-id.
What it all adds up to is that an expression of the form &A::x
has the type "pointer to member x
of class A
" if x
is a non-static member of a non-union class A
, and operator precedence has no influence on this.
这篇关于指针到成员的混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!