【问题标题】:How to call private virtual base class implementation when overriding in child class在子类中覆盖时如何调用私有虚拟基类实现
【发布时间】:2019-09-27 05:57:46
【问题描述】:

我有一个这样的类层次结构:

class Base
{
public:
  void start() { init(); }
private:
  virtual void init() = 0;
};

class Default : public Base
{
private:
  virtual void init() override {/*default implementation*/};
};

class Special : public Default
{
private:
  virtual void init() override final {/*specialized implementation*/};
}

如果我在 Special 类型的对象上调用 start(),这会正常工作;

现在我有一个案例,在Special 类的实现中,我想调用Default 类的实现。 通常这可以与Default::init(); 一起使用,但由于Defaults 声明这是private,所以这里会失败。

显然一种解决方案是将其从private 更改为protected,但我想问一下是否还有其他方法?我不想让任何孩子直接调用此函数,而是将其限制为通过 BaseDefault 类中已定义的虚函数发起的调用。

是否有一些选项或修饰符允许仅允许来自子类的成员函数调用,前提是它们位于(相同的)覆盖虚拟成员函数中?

【问题讨论】:

  • 我认为不,这是不可能的。这正是protected的用法,允许从具有public继承的孩子访问
  • 唯一能想到的就是把派生类做成friend
  • @songyuanyao 在这种情况下,我认为friendprotected 更邪恶;它将允许访问可能更多,并且需要修改基类,每个新的派生类都需要类似的访问......

标签: c++ inheritance virtual


【解决方案1】:

C++ 没有提供直接实现这一点的方法,因此您必须解决问题,例如。 G。在下面的一段代码中。

好吧,如果你绝对想要。我个人宁愿退回到使函数受到保护,记录它们的用途以及何时被调用,然后只相信派生类可以正确地做这些事情。这最终使界面保持清洁,并且不依赖于相当不寻常(也许是丑陋)的模式(实际上通过 this 两次)。

class Base
{
public:
    virtual ~Base() { }
    void start()
    {
        InitProxy p(*this);
        init(p);
    }
protected:
    class InitProxy
    {
    public:
        InitProxy(InitProxy const&) = delete;
        void init()
        {
            m_base.Base::init(*this);
        }
    private:
        friend class Base;
        Base& m_base;
        InitProxy(Base& base)
            : m_base(base)
        { }
    };
private:
    virtual void init(InitProxy& proxy) { }
};

class Derived : public Base
{
    void init(InitProxy& proxy) override
    {
        proxy.init();
    }
};

如果您想将此约束应用于多个函数,您可以让代理接受一个成员函数指针,这样您就不必分别为每个函数重新编写代理。如果函数参数不同,您可能需要从那时起制作模板。

【讨论】:

    【解决方案2】:

    转发声明Special,并使其成为Default的朋友:

    class Base
    {
    public:
      void start() { init(); }
    private:
      virtual void init() = 0;
    };
    
    class Special;  // Forward declaration
    class Default : public Base
    {
    private:
      virtual void init() override {/*default implementation*/}
      friend class Special; // Friend declaration
    };
    
    class Special : public Default
    {
    private:
      virtual void init() override final {
          Default::init();
          /*Other implementation*/
      }
    };
    

    【讨论】:

    • 然而friend 是邪恶的。
    猜你喜欢
    • 2012-03-17
    • 1970-01-01
    • 2010-11-22
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 1970-01-01
    相关资源
    最近更新 更多