Confusion between pointers and members

I am trying to understand the sequence in the error that occurs 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(); } 

Output 10 10 . I have indicated 4 points of the program, but (3) is my biggest problem:

  • x usually retrieved from within a member function.
  • x object is retrieved using the scope operator and the value l is returned to object x .
  • Given A::x , int lvalue is returned in (2), why then &A::x does not return int* , but instead returns int A::* ? The scope operator takes precedence over the & operator, so you should start A::x , returning the value of int l before the address is taken. those. should it be exactly the same as &(A::x) ? (By the way, adding brackets really works).
  • A little different, of course, is the scope operator, which refers to a member of the class, but without the object to which it belongs.

So, why exactly A::x does not return the address of the object x , but instead returns the address of the element, ignoring the priority :: to & ?

+7
c ++ c ++ 11 pointer-to-member
source share
2 answers

The C ++ standard does not explicitly specify operator precedence; it is possible to unequivocally derive operator priority from grammar rules, but this approach cannot evaluate a random special case like this that does not fit into the traditional operator priority model.

[expr.unary.op] / 3:

The result of the unary operator & is a pointer to its operand. The operand must be lvalue or identified-id. If the operand is a Qualified identifier denoting a non-static or variant member m some class C with type T , the result is of type 'pointer to a member of class C type T ' and is a prvalue value denoting C::m . Otherwise, if the type of the expression is T , the result is of type "pointer to T " and is a prvalue, which is the address of the assigned object or a pointer to the assigned function.

/4:

A pointer to an element is formed only when explicit & , and its operand is a qualified identifier, not enclosed in parentheses. [Note: that is, the expression &(qualified-id) , where the qualified identifier is enclosed in parentheses, does not form an expression such as "member pointer".

[expr.prim.general] / 9:

A nested qualifier name that designates a class, optionally followed by the template keyword, and then followed by the name of a member of this class or one of its base classes, is an identifier with qualifications.

What all of this means is that an expression of the form &A::x is of type “pointer to member x class A ” if x is a non-stationary member of a non-unit class A , and the operator’s priority does not affect this.

+3
source share

Basically, it is just that the syntax &A::x (unchanged) was chosen to indicate a pointer to a member.

If you write, for example, &(A::x) , you will get the usual pointer that you expect.

More information on member pointers, including a note about this property itself, can be found here .

+8
source share

All Articles