您好,我的这段代码有编译器错误(错误来自 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); }
};
根据我对运算符优先级的了解,这两个片段在我看来是等效的,因为 ::< /code> 的优先级高于 &
(例如,参见“联合打击战斗机系统开发和演示计划的C++编码标准")
但是它们是不同的......我认为这与“指向数据成员的指针”有关但我不知道它如何与运算符优先级相匹配。
有什么解释吗?
Hello I have this code with a compiler error (error is from 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'
};
while this code is error free:
class B {
protected:
int b;
};
class A : public B {
public:
void foo() { &(B::b); }
};
The two snippets seem to me equivalent based on my knowledge of the precedence of operators, because ::
has an higher precedence than &
(see for example table 2 at page 137 of "JOINT STRIKE FIGHTER AIR VEHICLE C++ CODING STANDARDS FOR THE SYSTEM DEVELOPMENT AND DEMONSTRATION PROGRAM" )
But they are different... I think it is something related to "pointer-to-data-member" but I do not know how does it fit with the operators precedence.
Any explanation?
发布评论
评论(3)
在第一种情况下,您将获取指向成员
B::b
的指针的地址。由于这样的指针不是A
的父级成员,而是一个单独的对象,因此它无法通过受保护的机制访问它。在第二种情况下,您需要获取
b
的特定实例的地址,用其基类对其进行限定,以便在多重继承的情况下编译器会知道你指的是哪个基类。在这种情况下,受保护的属性是可见的。请注意,此编译:
作为一个添加的示例,它不起作用,其原因与以下(希望更熟悉)代码不起作用相同:
In the first case you're taking the address of pointer-to-member
B::b
. Since such a pointer is NOT a member of the parent ofA
but a separate object, it can't access it via the protected mechanism.In the SECOND case where it works you're asking for the address of the specific instance of
b
, qualifying it with its base class so that in the case of multiple inheritance the compiler would know which base class you mean. In this context the protected attribute is visible.Note that this compiles:
As an added example it doesn't work for the same reason that the following (hopefully more familiar) code doesn't work:
这只是一个补充。
§5.3.1/2 说:
根据§5.1/7,
B::b
属于qualified-id case,但(B::b)
则不然。因此,编译器将其解释为左值。
This is just a supplementation.
§5.3.1/2 says:
According to §5.1/7,
B::b
comes under the qualified-id case, but(B::b)
doesn't.So, compiler interprets it as an lvalue.
当您尝试返回值时,这两个语句之间的差异变得更加明显:
您想要做的是通过 A 对象访问它:
从 A 开始,您可以访问它。
通过 B 访问它就像从外部访问它一样,从而触发访问说明符。
The differece between the two statements becomes more obvious when you try and return the value:
What you want to do is access it via the A object:
As from the A you are allowed to access it.
Accessing it via B like that is accessing it from outside and thus triggers the access specifiers.