假设一个类Y
公开继承一个类X
。一个类可以在公开继承的同时Z
私下继承吗?Y
X
为了更清楚地说明这一点,假设X
定义了公共方法x1
和x2
. Y
继承X
、覆盖x1
并提供方法y
。C++ 是否允许第三个类Z
以Y
这样的方式进行子类化,即它Y
的实现x1
和y
私有可用,而外部世界只看到它X
公开继承,即只有一个公共方法x2
?
假设一个类Y
公开继承一个类X
。一个类可以在公开继承的同时Z
私下继承吗?Y
X
为了更清楚地说明这一点,假设X
定义了公共方法x1
和x2
. Y
继承X
、覆盖x1
并提供方法y
。C++ 是否允许第三个类Z
以Y
这样的方式进行子类化,即它Y
的实现x1
和y
私有可用,而外部世界只看到它X
公开继承,即只有一个公共方法x2
?
是的,这称为虚拟继承。
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;
};
这对我来说看起来更熟悉。
当然。您可以using X::x2
在一个public:
部分中使用。当然,如果 Y 覆盖 x2,那么您将忽略此覆盖。
首先,我不太确定我理解你的最后一句话。
C++ 是否允许第三类 Z 子类化 Y,使得 Y 对 x1 和 y 的实现对其私有可用,而外界只看到它公开继承 X,即只有一个公共方法 x2?
如果Z
从公开继承X
,那么两者x1
和x2
都将可用:尽管可访问性x2
可能会改变Z
,但没有什么能阻止外部世界Z
通过X
指针和调用来操作 a x2
。
话虽如此,但正如 Johannes 所指出的那样,您还可以Z
从私有继承Y
和公开继承,您应该研究虚拟继承,因为它将因此继承两次from 。X
Z
X
根据您的需要,您可能还想研究装饰器模式(也许它完全不相关,但由于某种原因,通过阅读您的问题,我觉得这是您想要实现的目标):
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
实现。
我认为 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;
};
如果您在至少一个地方使用 X 的非虚拟继承,您将获得两个不同的 X 子对象,它们具有不同的访问路径和访问权限。
如果您在两个地方都使用 X 的虚拟继承,那么您应该在两个地方都使用公共继承,因为无法强制通过虚拟继承进行访问。如果您将一个派生设为非公开,您仍然可以使用另一条路径来获得访问权限。如果两个派生都不是公共的,您可以只派生另一个类,因此,类型系统不能强制执行非公共虚拟继承,因此这是无稽之谈,并且在语言中永远不应该被允许。