如何从派生类访问基类中的受保护方法?

时间:2011-01-12 18:23:41

标签: c++ protected derived-class

以下是让我烦恼的代码示例:

class Base {
  protected:
    virtual void foo() = 0;
};

class Derived : public Base {
  private:
    Base *b; /* Initialized by constructor, not shown here
                Intended to store a pointer on an instance of any derived class of Base */

  protected:
    virtual void foo() { /* Some implementation */ };
    virtual void foo2() {
      this->b->foo(); /* Compilator sets an error: 'virtual void Base::foo() is protected' */
    }
};

如何访问受保护的覆盖函数?

感谢您的帮助。 :O)

6 个答案:

答案 0 :(得分:10)

基类中的受保护成员只能由当前对象访问 因此,您可以拨打this->foo(),但不允许您拨打this->b->foo()。这与Derived是否为foo提供实现无关。

这种限制背后的原因是,它可以很容易地规避受保护的访问。你只需创建一个像Derived这样的类,突然你也可以访问外部人员无法访问的其他类的部分(如OtherDerived)。

答案 1 :(得分:6)

通常,您可以使用Base::foo()来执行此操作,{{1}}引用当前实例的基类。

但是,如果您的代码需要以您尝试的方式执行而且不允许,那么您需要将foo()设为public或使Derived成为Base的朋友。

答案 2 :(得分:2)

一种解决方案是在Base中声明一个静态保护函数,将调用重定向到私有/受保护函数(示例中为foo)。

让我们说:

class Base {
protected:
    static void call_foo(Base* base) { base->foo(); }
private:
    virtual void foo() = 0;
};

class Derived : public Base {
private:
    Base* b;
protected:
    virtual void foo(){/* Some implementation */};
    virtual void foo2()
    {
        // b->foo(); // doesn't work
        call_foo(b); // works
    }
};

这样,我们不会破坏封装,因为Base的设计者可以明确选择允许所有派生类相互调用foo,同时避免放置foo进入公共接口或明确地将Base的所有可能子类转换为朋友。

此外,无论foo是否为虚拟,或者是私有还是受保护,此方法都有效。

Here是上面代码运行版本的链接,here是同一个想法的另一个版本,带有更多的业务逻辑。

答案 3 :(得分:1)

它有点脆弱,但是你在这里定义的类不会起作用吗?

virtual void foo2() {
  reinterpret_cast<Derived *>(this->b)->foo(); 
}

reinterpret_cast指向基础对象的VTABLE,并通过此成员访问器调用它。

答案 4 :(得分:0)

使用范围运算符(Base :: foo())显式调用基函数。但是在这种情况下,Base类没有定义foo(它是纯虚拟的),所以当你说this->b->foo();时实际上没有函数可以执行,因为b是指向Base而不是Derived的指针。

答案 5 :(得分:0)

  

您如何访问受保护的   压倒一切的功能?

---从哪里来?

您只能通过继承访问受保护的成员(除了同一个类的方法)。比方说,您有class Derived1继承自DerivedDerived1的对象可以调用foo()

编辑:MSDN article关于受保护的访问说明符。