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

时间:2011-02-16 15:50:15

标签: 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'
};

虽然此代码没有错误:

class B
{
protected:
int b;
};

class A : public B
{
public:
void foo(){ &(B::b); }
};

根据我对运算符优先级的了解,这两个片段在我看来是等价的,因为::的优先级高于& (参见“联合打击机驾驶员C ++编码系统开发和示范计划编码标准”第137页表2)http://www2.research.att.com/~bs/JSF-AV-rules.pdf

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

有任何解释吗?

谢谢你, 的Alessandro

3 个答案:

答案 0 :(得分: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::
};

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

class B
{
protected:
int b;
};

class A : public B
{
public:
void foo(const B* b_obj) { b_obj->b; }
};

答案 1 :(得分:7)

这只是补充 §5.3.1/ 2说:

  

一元&的结果运营商是   指向其操作数的指针。操作数   应该是左值或合格身份证。   在第一种情况下,如果是类型的   表达式是“T”,类型   结果是“指向T的指针”   ...
  为一个   qualified-id,...如果成员是   类的C类非静态成员   T,结果的类型是“指针   到类型T的C类成员。“

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

答案 2 :(得分: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

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

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

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