Reputation: 63710
The scenario generating this is quite complex so I'll strip out a few pieces and give an accurate representation of the classes involved.
/* This is inherited using SI by many classes, as normal */
class IBase
{
virtual string toString()=0;
};
/* Base2 can't inherit IBase due to other methods on IBase which aren't appropriate */
class Base2
{
string toString()
{
...
}
};
/* a special class, is this valid? */
class Class1 : public IBase, public Base2
{
};
So, is this valid? Will there be conflicts on the toString? Or can Class1 use Base2::toString to satisfy IBase? Like I say there are lots of other things not shown, so suggestions for major design changes on this example are probably not that helpful... though any general suggestions/advice are welcome.
My other thought was something like this:
class Class1 : public IBase, public Base2
{
virtual string toString()
{
return Base2::toString();
}
};
This builds and links, but I've no idea if it has hidden bugs.
Upvotes: 6
Views: 299
Reputation: 49156
This should work just fine.
You're properly overriding the IBase interface to provide a definition of ToString()
that will be forwared up to Base2::ToString()
.
Note that Base2
doesn't declare toString() as virtual, so Class1
can't override the behavior of Base2::ToString
. No ambiguity there.
And, in addition, this is not the classic diamond problem in multiple inheritance solved by virtual inheritance because they don't share a base class.
Upvotes: 1
Reputation: 76640
You can fix this using "virtual inheritance".
Consider creating a common base class that only defines a pure virtual toString
method (or, in reality, pure virtual version of whatever methods it makes sense for both IBase
and Base2
to have), e.g.
class Stringable {
public:
virtual string toString() = 0;
};
Then, have both IBase
and Base2
inherit from this Stringable
class:
class IBase : public Stringable
{
};
class Base2 : public Stringable
{
public:
virtual string toString()
{ ... }
};
Now this as it is still won't work because Class1
will have inherited two copies of the Stringable
base class, only one of which has an implementation for toString
in its inheritance hierarchy. This is known as the "dreaded diamond". However, if IBase
and Base2
were to inherit virtually from Stringable
, like this:
class IBase : virtual public Stringable
{
};
class Base2 : virtual public Stringable
{
public:
virtual string toString()
{ ... }
};
Then this tells the compiler that there should only be one common Stringable
base class even if IBase
and Base2
are both inherited by one class, which is exactly what you want, because then the Base2::toString
is used for Class1
.
Your second idea has no "hidden bugs", but is somewhat of a pain in the butt to implement repeatedly, as you probably realize.
Upvotes: 2