简体   繁体   English

指针到成员的混乱

[英]Pointer-to-member confusion

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 . 输出为10 10 I labelled 4 points of the program, but (3) is my biggest concern: 我给程序标记了4分,但是(3)是我最大的担忧:

  1. x is fetched normally from inside a member function. x通常是从成员函数内部获取的。
  2. x of the object is fetched using the scope operator and an lvalue to the object x is returned. x的对象是取出使用范围运算符和一个左值到对象x被返回。
  3. Given A::x returned an int lvalue in (2), why then does &A::x return not int* but instead returns int A::* ? 给定A::x在(2)中返回一个int左值,为什么&A::x不返回int*而是返回int A::* The scope operator even takes precedence before the & operator so A::x should be run first, returning an int lvalue, before the address is taken. 范围运算符甚至优先于&运算符,因此应在获取地址之前先运行A::x ,并返回一个int左值。 ie this should be the same as &(A::x) surely? 即这肯定&(A::x)相同吗? (Adding parentheses does actually work by the way). (顺便说一句,添加括号确实有效)。
  4. 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 & ? 那么,为什么A::x不返回对象x的地址,而是返回成员的地址,而忽略::&之前的优先级呢?

Basically, it's just that the syntax &A::x (without variation) has been chosen to mean pointer-to-member. 基本上,只是选择&A::x语法(无变化)来表示成员指针。

If you write, for example, &(A::x) , you will get the plain pointer you expect. 例如,如果编写&(A::x) ,则将获得所需的普通指针。

More information on pointers-to-members, including a note about this very property, can be found here . 此处可以找到有关指向成员的指针的更多信息,包括有关此属性的注释。

The C++ standard doesn't explicitly specify operator precedence; C ++标准未明确指定运算符优先级; 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: [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 . 操作数应为左值或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 . 如果操作数是一个合格的id ,它使用类型T命名某些C类的非静态或变体成员m ,则结果的类型为“指向类型TC类成员的指针”,并且是一个指定C::m的prvalue。 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. 否则,如果表达式的类型为T ,则结果的类型为“指向T的指针”,并且是prvalue,它是指定对象的地址或指向指定函数的指针。

/4: / 4:

A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses. 仅当使用显式&且其操作数是未括在括号中的限定ID时,才会形成指向成员的指针。 [ 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'. [ 注意:即,表达式&(qualified-id)不能将类型为pointer to member的表达式形成为表达式,其中qualified-id用括号括起来。

[expr.prim.general]/9: [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 . 表示一个类的nested-name-specifier是一个qualified-id ,该类后面可以是关键字template ,然后是该类或其基类之一的成员的名称。

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. 如果x是非联盟类A的非静态成员,并且运算符优先级没有,则&A::x形式的表达式的类型总和是“指向类A成员x的指针”。影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM