Simultaneous private and public inheritance in C++
Suppose a class Y
publicly inherits a class X
. Is it possible for a class Z
to privately inherit Y
while publicly inheriting X
?
To make this clearer, suppose X
defines public methods x1
and x2
. Y
inherits 开发者_如何学PythonX
, overrides x1
and provides a method y
. Does C++ allow for a third class Z
to subclass Y
in such a way that Y
's implementation of x1
and y
are privately available to it, while the outside world only sees it inheriting X
publicly, i.e. having only a single public method x2
?
Yes, this is called virtual inheritance.
struct X {
virtual void x1();
void x2();
};
struct Y : virtual X {
void x1(); // overrides
void y();
};
struct Z : private Y, virtual X {
};
People cannot do z.y()
or z.x1()
but they can do z.x2()
and can convert a Z*
to a X*
. However once they do so, they can call converted->x1()
and converted->x2()
, of course.
You haven't said anything about your goal, but it sounds like you really want to keep Y
as a pointer though
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;
};
This looks more familiar to me.
Sure. You could use using X::x2
in a public:
section. Of course, if Y overrides x2, then you will be ignoring this override.
First of all, I not quite sure I understand your last sentence.
Does C++ allow for a third class Z to subclass Y in such a way that Y's implementation of x1 and y are privately available to it, while the outside world only sees it inheriting X publicly, i.e. having only a single public method x2?
If Z
inherits publicly from X
, then both x1
and x2
will be available : although accessibility of x2
may be changed in Z
, nothing prevents the outside world from manipulating a Z
through a X
pointer and call x2
.
That being said, you might as well have Z
inherit privately from Y
and publicly from X
though, as pointed out by Johannes, you should look into virtual inheritance as Z
will thus inherit twice from X
.
Depending on your needs, you might also want to look into the decorator pattern (maybe it's completely unrelated, but for some reason, I feel through reading your question that it's what you want to achieve) :
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);
}
In this quick and dirty code sample, Z
is a X
(public inheritance), yet is reuses Y
implementation.
I think that using statement fills better this role, it allows you to specify on Z which private methods will be available:
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;
};
If you use non-virtual inheritance of X in at least one place you get two distinct X subobjects with distinct access paths and access rights.
If you use virtual inheritance of X in both places you should be using public inheritance in both places since access via virtual inheritance cannot be enforced. If you make one derivation non-public you will still be able to use the other path to gain access. If neither derivation is public you can just derive another class in which it is, hence, non-public virtual inheritance can't be enforced by the type system and so it is nonsense and should never have been permitted in the language.
精彩评论