我试图了解此程序中引发的错误的一致性:
#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();
}
输出为10 10
。我标记了该计划的4个点,但(3)是我最关心的问题:
x
通常从成员函数内部获取。x
,并返回对象x
的左值。A::x
在(2)中返回了int
左值,为什么&A::x
不返回int*
而是返回int A::*
?范围运算符甚至优先于&
运算符,因此应首先运行A::x
,在获取地址之前返回int
左值。即这肯定与&(A::x)
相同? (添加括号实际上确实有效)。 那么为什么A::x
确实没有返回对象x
的地址,而是返回成员的地址,忽略::
之前&
的优先级?
答案 0 :(得分:8)
答案 1 :(得分:3)
C ++标准没有明确指定运算符优先级;可以从语法规则中隐含地推导出运算符优先级,但是这种方法无法理解像这样的偶然特殊情况,它不适合传统的运算符优先级模型。
[expr.unary.op] / 3:
一元
&
运算符的结果是指向其操作数的指针。操作数应为左值或 qualified-id 。如果操作数是a qualified-id 命名类型为m
的某个类C
的非静态或变体成员T
,结果具有类型'指向类成员的指针{ {1}}类型C
'并且是指定T
的prvalue。否则,如果表达式的类型为C::m
,则结果具有类型'指向T
'的类型,并且是一个prvalue,它是指定对象的地址或指向指定函数的指针。
/ 4:
只有在使用显式
T
并且其操作数是 qualified-id 未括在括号中时,才会形成指向成员的指针。 [注意: 也就是说,表达式&
,其中 qualified-id 括在括号中,不会形成“指向成员的指针”类型的表达式。
[expr.prim.general] / 9:
nested-name-specifier 表示一个类,可选地后跟关键字
&(qualified-id)
,然后是该类或其基类之一的成员名称类,是 qualified-id 。
如果template
是非&A::x
,则x
形式的表达式具有类型“指向A
类成员x
”的类型非联合类A
的静态成员,运算符优先级对此没有影响。