指向成员的混淆

时间:2016-01-21 22:30:58

标签: c++ c++11 pointer-to-member

我试图了解此程序中引发的错误的一致性:

#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)是我最关心的问题:

  1. x通常从成员函数内部获取。
  2. 使用范围运算符提取对象的
  3. x,并返回对象x的左值。
  4. 鉴于A::x在(2)中返回了int左值,为什么&A::x不返回int*而是返回int A::*?范围运算符甚至优先于&运算符,因此应首先运行A::x,在获取地址之前返回int左值。即这肯定与&(A::x)相同? (添加括号实际上确实有效)。
  5. 当然有点不同,范围操作符引用类成员但没有引用的对象。
  6. 那么为什么A::x确实没有返回对象x的地址,而是返回成员的地址,忽略::之前&的优先级?

2 个答案:

答案 0 :(得分:8)

基本上,只是选择了语法&A::x(没有变化)来表示指向成员的指针。

如果您编写&(A::x),那么您将得到您期望的普通指针。

有关成员指针的更多信息,包括有关此属性的说明,可以找到here

答案 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的静态成员,运算符优先级对此没有影响。