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

发布于 2024-10-17 11:06:22 字数 704 浏览 3 评论 0 原文

您好,我的这段代码有编译器错误(错误来自 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苯莒 2024-10-24 11:06:22

在第一种情况下,您将获取指向成员 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; }
};

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 of A 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:

class B
{
protected:
int b;
};

class A : public B
{
public:
void foo(){ &A::b; }  // Note here &A:: instead of &B::
};

As an added example it doesn't work for the same reason that the following (hopefully more familiar) code doesn't work:

class B
{
protected:
int b;
};

class A : public B
{
public:
void foo(const B* b_obj) { b_obj->b; }
};
沒落の蓅哖 2024-10-24 11:06:22

这只是一个补充。
§5.3.1/2 说:

一元 & 的结果运算符是
指向其操作数的指针。操作数
应为左值或合格 ID。
在第一种情况下,如果
表达式是“T”,类型
结果是“指向 T 的指针”。
...
对于一个
合格的 id,...如果该成员是
类型 C 类的非静态成员
T,结果类型为“指针
为 T 型 C 类成员。”

根据§5.1/7,B::b属于qualified-id case,但(B::b)则不然。
因此,编译器将其解释为左值。

This is just a supplementation.
§5.3.1/2 says:

The result of the unary & operator is
a pointer to its operand. The operand
shall be an lvalue or a qualified-id.
In the first case, if the type of the
expression is “T,” the type of the
result is “pointer to T.”
...
For a
qualified-id, ... If the member is a
non-static member of class C of type
T, the type of the result is “pointer
to member of class C of type T.”

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.

她比我温柔 2024-10-24 11:06:22

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

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 访问它就像从外部访问它一样,从而触发访问说明符。

The differece between the two statements becomes more obvious when you try and return the value:

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

What you want to do is access it via the A object:

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文