可以使用static_cast颠覆受保护成员的访问检查吗?

时间:2019-02-14 23:02:39

标签: c++ language-lawyer

考虑

class A {
  protected:
    int m;
};
class B : public A {
    void foo(A& a) {
        a.m = 42;  // ill-formed
    }
    void bar(A& a) {
        auto pm = &B::m;
        auto pm2 = static_cast<int A::*>(pm);
        a.*pm2 = 42;  // is this ok?
    }
};

根据[class.protected],尝试直接访问A::m的格式不正确。但是,似乎我们总是可以使用static_cast(?)来规避这一点,该方法允许使用指向成员的指针进行从派生到基的转换。还是不知何故是UB?

[{Coliru link显示bar已编译]

1 个答案:

答案 0 :(得分:4)

是的,您可以通过使用static_cast来绕过受保护的机制。

在这种情况下,我认为这不是 不确定的行为。

通过使用static_cast,您可以告诉编译器两件事:

  1. 您要求编译器将B指针转换为A指针。

  2. 您告诉编译器这样做是可以的。

对于1.编译器会进行非常有限的检查,以检查是否可以,对于static_cast,编译器可以将其从派生转换为基数,反之亦然。所以编译器很高兴。变量或指针是受保护的还是公共的,都不属于变量或指针类型的一部分。 pmpm2都不携带protected信息。

对于2.编译器完全由您自己决定是否可以在您的设计中做出决定。这不是未定义的行为。这可能仍然不是一个好主意。 pm2只是指向A中int的指针。您可以将其重置为指向公开的int中其他A的指针。

背景是C ++中的访问控制通常是按类的,再加上protected周围还有一些额外的规则,它们试图在每个实例的基础上提供某种级别的访问控制,但是这种保护并不完美正如您在有趣的问题中所展示的那样。