你好,我有一个编译器错误的代码(错误来自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); }
};根据我对运算符优先级的了解,这两个代码片段在我看来是等价的,因为::的优先级比&高(例如,请参阅"JOINT STRIKE FIGHTER AIR VEHICLE C++ CODING STANDARDS FOR THE SYSTEM DEVELOPMENT AND DEMONSTRATION PROGRAM“第137页的表2)。
但它们是不同的..。我认为它与“指向数据成员的指针”有关,但我不知道它如何符合运算符的优先顺序。
有什么解释吗?
发布于 2011-02-17 00:05:12
在第一种情况下,您将获取指向成员的指针B::b的地址。因为这样的指针不是A父对象的成员,而是一个单独的对象,它不能通过protected机制访问它。
在第二种情况下,您将询问特定b实例的地址,并使用其基类对其进行限定,以便在多重继承的情况下,编译器将知道您所指的是哪个基类。在此上下文中,protected属性是可见的。
请注意,这段代码将进行编译:
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; }
};发布于 2011-02-17 01:07:44
这只是一个补充。
§5.3.1/2表示:
一元&运算符的结果是指向其操作数的指针。操作数应为左值或限定id。在第一种情况下,如果表达式的类型是“T”,则结果的类型是“指向T的指针”...
对于合格的id,...如果该成员是类型T的类C的非静态成员,则结果的类型是“指向类型T的类C的成员的指针”。
根据§5.1/7,B::b属于限定id的情况,但(B::b)不属于限定id的情况,所以编译器将其解释为左值。
发布于 2011-02-17 00:12:36
当您尝试返回值时,这两个语句之间的差异会变得更加明显:
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访问它就是从外部访问它,从而触发访问说明符。
https://stackoverflow.com/questions/5018603
复制相似问题