【问题标题】:Simultaneous private and public inheritance in C++C++ 中的同时私有和公共继承
【发布时间】:2011-05-31 14:05:42
【问题描述】:

假设一个类Y公开继承一个类XZ 的类是否可以在公开继承X 的同时私下继承Y

为了更清楚,假设X 定义了公共方法x1x2Y 继承 X,覆盖 x1 并提供方法 y。 C++ 是否允许将第三类Z 子类化为Y,使得Yx1y 的实现对其私有可用,而外界只看到它继承@987654338 @public,即只有一个公共方法x2?

【问题讨论】:

  • 如果你也想“懒惰的助手”来帮助你,我会尽可能把这个问题写在代码中,然后指出它不起作用的地方,然后将问题简化为一个行,询问如何使这项工作。

标签: c++ inheritance virtual-functions virtual-inheritance private-inheritance


【解决方案1】:

是的,这称为虚拟继承。

struct X {
  virtual void x1();
  void x2();
};

struct Y : virtual X {
  void x1(); // overrides
  void y();
};

struct Z : private Y, virtual X { 

};

人们不能执行z.y()z.x1(),但他们可以执行z.x2() 并且可以将Z* 转换为X*。但是,一旦他们这样做了,他们当然可以致电converted->x1() converted->x2()

你没有说你的目标,但听起来你真的想把Y作为一个指针

struct X {
  virtual void x1();
  void x2();
};

struct Y : X {
  virtual void x1(); // overrides
  void y();
};

struct Z : X { 
  virtual void x1() { // overrides
    /* uses y->x1 */ 
  }
  Y *y;
};

这对我来说看起来更熟悉。

【讨论】:

  • 感谢您的明确回答,让我了解了一个我以前不知道的概念,这正是我想要填补的角色。很抱歉问了一个看似微不足道的问题。当你不知道它叫什么时,很难知道它是微不足道的:-)
【解决方案2】:

当然。您可以在 public: 部分中使用 using X::x2。当然,如果 Y 覆盖 x2,那么您将忽略此覆盖。

【讨论】:

    【解决方案3】:

    首先,我不太确定我理解你的最后一句话。

    C++ 是否允许第三类 Z Y 的子类,使得 Y 的 x1 和 y 的实现是 私下提供给它,而 外界只看到它继承 X 公开,即只有一个 公共方法 x2?

    如果Z 公开继承自X,那么x1x2 都将可用:尽管x2 的可访问性可能Z 中更改,但没有什么可以阻止外部世界通过X指针操纵Z并调用x2

    话虽如此,你也可以让Z 私下继承 Y 并公开继承 X 虽然,正如 Johannes 所指出的,你应该研究虚拟继承,因为 Z 将因此继承 两次来自X


    根据您的需要,您可能还想查看decorator pattern(也许它完全不相关,但由于某种原因,通过阅读您的问题,我觉得这是您想要实现的目标):

    class X
    {
    public:
        virtual void x1();
        virtual void x2();
    };
    
    class Y : public X
    {
    public:
        virtual void y();
        virtual void x1();
    };
    
    class Z : public X
    {
    public:
        explicit Z(X *x) : x_(x) {}
    
        virtual void x1() { x_->x1(); }
        virtual void x2() { x_->x2(); }
    
    private:
        X *x_;
    };
    
    int main()
    {
        Y y;
        Z z(&y);
    }
    

    在这个快速而肮脏的代码示例中,Z 是一个 X(公共继承),但却是重用 Y 实现。

    【讨论】:

    • 显式关键字是什么?
    • 很好,你用“把 y 作为指针”的方式打败了我!我知道它有一个名字,但我一辈子都想不通它叫“装饰者”:)
    • 也是一个非常有启发性的答案。特别感谢您让我知道explicit
    【解决方案4】:

    我认为 using 语句更适合这个角色,它允许您在 Z 上指定哪些私有方法可用:

    class X
    {
        public:
            virtual void x1() {}
            virtual void x2() {}
    
    };
    
    class Y: public X
    {
    public:
        virtual void x1() {}
    };
    
    class Z: private Y
    {
    public:
        using X::x2;
    
    };
    

    【讨论】:

      【解决方案5】:

      如果您在至少一个地方使用 X 的非虚拟继承,您将获得两个具有不同访问路径和访问权限的不同 X 子对象。

      如果您在两个地方都使用 X 的虚拟继承,则应该在两个地方都使用公共继承,因为无法强制通过虚拟继承进行访问。如果您将一个派生设为非公开,您仍然可以使用另一条路径来获得访问权限。如果两个派生都不是公共的,您可以只派生另一个类,因此,非公共虚拟继承不能由类型系统强制执行,因此这是无稽之谈,并且在语言中绝不应该允许。

      【讨论】:

        猜你喜欢
        • 2011-03-11
        • 2011-08-10
        • 2011-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-07
        相关资源
        最近更新 更多