指向成员的指针混淆

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; //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 的左值是 returned.
  4. 给定 A::x return 在 (2) 中编辑了一个 int 左值,为什么 &A::x return 不是 int* 而是returns int A::*?范围运算符甚至优先于 & 运算符,因此 A::x 应该首先是 运行,returning 一个 int 左值,然后再获取地址。也就是说,这肯定与 &(A::x) 相同吗? (顺便说一下,添加括号确实有效)。
  5. 当然这里有点不同,作用域运算符引用 class 成员但没有引用对象。

那么为什么 A::x 不是 return 对象的地址 x 而是 return 成员的地址,忽略 [=26] 的优先级=] 在 &?

之前

基本上,只是选择语法 &A::x(没有变化)来表示 pointer-to-member。

如果你写,例如,&(A::x),你会得到你期望的普通指针。

有关 pointers-to-members 的更多信息,包括关于此非常 属性 的注释,请参见 here

C++ 标准没有明确指定运算符优先级;可以从语法规则中隐式地推断出运算符优先级,但这种方法无法理解像这样的特殊情况,它不适合传统的运算符优先级模型。

[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 member m of some class C with type T, the result has type 'pointer to member of class C of type T' and is a prvalue designating C::m. Otherwise, if the type of the expression is T, the result has type 'pointer to T' 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.

如果 x 是 non-union 的 non-static 成员,则 &A::x 形式的表达式的类型为 "pointer to member x of class A" =] class A,运算符优先级对此没有影响。