您好我的代码有编译错误(错误来自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
答案 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访问它就是从外部访问它,从而触发访问说明符。