1

假设一个类Y公开继承一个类X。一个类可以在公开继承的同时Z私下继承吗?YX

为了更清楚地说明这一点,假设X定义了公共方法x1x2. Y继承X、覆盖x1并提供方法y。C++ 是否允许第三个类ZY这样的方式进行子类化,即它Y的实现x1y私有可用,而外部世界只看到它X公开继承,即只有一个公共方法x2

4

5 回答 5

4

是的,这称为虚拟继承。

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()并且可以将 a 转换Z*为 a X*。但是,一旦他们这样做了,他们当然可以调用converted->x1() and 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;
};

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

于 2010-12-28T13:30:34.143 回答
2

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

于 2010-12-28T13:29:20.160 回答
2

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

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

如果Z从公开继承X,那么两者x1x2都将可用:尽管可访问性x2 可能会改变Z,但没有什么能阻止外部世界Z通过X指针和调用来操作 a x2

话虽如此,但正如 Johannes 所指出的那样,您还可以Z从私有继承Y和公开继承,您应该研究虚拟继承,因为它将因此继承两次from 。XZX


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

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实现。

于 2010-12-28T13:37:33.497 回答
2

我认为 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;

};
于 2010-12-28T14:21:11.113 回答
0

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

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

于 2010-12-28T22:49:33.770 回答