假设某个班级Y
公开继承了一个班级X
。在公开继承Z
时,课程Y
是否可以私下继承X
?
为了更清楚,假设X
定义了公共方法x1
和x2
。 Y
继承X
,覆盖x1
并提供方法y
。 C ++是否允许第三个类Z
以Y
的{{1}}实现Y
和x1
为子类y
进行子类化,而外界只看到它公开继承X
,即只有一个公共方法x2
?
答案 0 :(得分: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()
并且可以将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;
};
这对我来说更为熟悉。
答案 1 :(得分:2)
不确定。您可以在using X::x2
部分中使用public:
。当然,如果Y覆盖x2,那么你将忽略这个覆盖。
答案 2 :(得分:2)
首先,我不太清楚我理解你的最后一句话。
C ++是否允许使用第三类Z. 子类Y以Y的方式 x1和y的实现是 私人可用,而 外界只看到它继承 公开X,即只有一个 公共方法x2?
如果Z
从X
公开继承,则x1
和x2
都可用:虽然x2
的可访问性可能在Z
中进行更改,不会阻止外部世界通过Z
指针操纵X
并致电x2
。
话虽如此,您可能Z
私下从Y
继承并公开从X
继承,但正如Johannes所指出的,您应该将虚拟继承看作Z
。因此,1}}将从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
实施
答案 3 :(得分: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;
};
答案 4 :(得分:0)
如果在至少一个地方使用X的非虚拟继承,则会获得具有不同访问路径和访问权限的两个不同的X子对象。
如果在两个地方使用X的虚拟继承,则应该在两个地方都使用公共继承,因为无法通过虚拟继承进行访问。如果您将一个派生非公开,您仍然可以使用其他路径获取访问权限。如果这两个派生都不是公共的,那么你只能派生出另一个类,因此,类型系统不能强制执行非公共虚拟继承,因此它是无意义的,并且永远不应该被允许使用该语言。