关于C++运算符"地址"和"范围解析"优先级的问题

Ale*_*son 23 c++ operator-precedence pointer-to-member

您好我有这个代码与编译器错误(错误来自Microsoft Visual Studio 2008):

class B
{
protected:
int b;
};

class A : public B
{
public:
void foo(){ &B::b; }//  error C2248: 'B::b' : cannot access protected member declared in class 'B'
};
Run Code Online (Sandbox Code Playgroud)

虽然此代码没有错误:

class B
{
protected:
int b;
};

class A : public B
{
public:
void foo(){ &(B::b); }
};
Run Code Online (Sandbox Code Playgroud)

基于我对运算符优先级的了解,这两个片段在我看来是等价的,因为::具有比&更高的优先级(例如参见"联合攻击战斗机车辆C++编码系统开发和编码标准"第137页的表2)演示计划" http://www2.research.att.com/~bs/JSF-AV-rules.pdf)

但它们是不同的...我认为它与"指向数据成员"有关,但我不知道它如何与运算符优先级相符.

任何解释?

谢谢,亚历山德罗

Mar*_*k B 13

在第一种情况下,您将获取指向成员的地址B::b.由于这样的指针不是父节点的成员A而是单独的对象,因此它无法通过受保护机制访问它.

在它的工作原理你要求的地址第二种情况下的具体实例b,与它的基类限定它,这样在多重继承的情况下,编译器会知道你的意思,其基类.在此上下文中,受保护的属性是可见的.

请注意,这编译:

class B
{
protected:
int b;
};

class A : public B
{
public:
void foo(){ &A::b; }  // Note here &A:: instead of &B::
};
Run Code Online (Sandbox Code Playgroud)

作为一个附加示例,它不起作用的原因与以下(希望更熟悉)代码不起作用的原因相同:

class B
{
protected:
int b;
};

class A : public B
{
public:
void foo(const B* b_obj) { b_obj->b; }
};
Run Code Online (Sandbox Code Playgroud)

  • 标准中有关语法和差异的任何参考?这个语法如何`&(B :: b)`意味着`b`属于`A`的特定实例? (2认同)
  • @Matthieu:是的.我明白`B :: b`是什么意思.我其实想问一下有什么特别的括号才能有所不同? (2认同)

Ise*_*ria 7

这只是补充.
§5.3.1/ 2说:

一元&运算符的结果是指向其操作数的指针.操作数应为左值或限定ID.在第一种情况下,如果表达式的类型是"T",则结果的类型是"指向T的指针"...
对于qualified-id,...如果成员是非静态成员类型为T的类C,结果的类型是"指向类型T的C类成员的指针".

根据§5.1/ 7,B::b属于qual -id案件,但(B::b)没有.因此,编译器将其解释为左值.


Mar*_*ork 6

当您尝试返回值时,两个语句之间的差异变得更加明显:

int*     foo()    { return &(B::b);}  // This is a pointer to an int


int A::* foo()    { return &B::b; }   // This is a pointer to a member of type int
Run Code Online (Sandbox Code Playgroud)

你想要做的是通过A对象访问它:

int A::* foo()    { return &A::b; }   // This is a pointer to a member of type int
Run Code Online (Sandbox Code Playgroud)

从A开始,您可以访问它.
通过B访问它就是从外部访问它,从而触发访问说明符.