Reputation: 8359
This is an attempt to understand the impact of using virtual base class inheritance, especially regarding runtime cost. The situation I have in mind also involves Interfaces (or ABC s for that).
I----------
/ | \ |
D1 D2 D3 Isub
| /
D3Dec
So, we have an Interface I
and we have different implementations D1
, D2
, and D3
. But now the twist is, there is a special decorator, which wraps just some (arbitrary) I
implementation and then adds an extended feature based on the contract expressed through I
.
Thus, from a logical or design viewangle, it would be desirable to express that extended ability through a sub-interface Isub
derived from I
. Thus any Isub
automatically also fulfils the I
contract.
Now, to implement such in C++, any implementation of interface I
must be done virtual
, and likewise, Isub
must inherit virtual
from I
, otherwise we'd end up with two I
subobjects residing in D3Dec
.
I
has to pay the price in terms of memory layout with tricky virtual base offset adjustments. Correct?I
and Isub
are pure virtual, i.e. have no members and only pure virtual functions? Would it then be possible to make that work without virtutal inheritance?Isub
. If clients call the extended functionality, they actually call into the implementation of said functionality within D3Dec
, and this in turn uses the other I
-functionality to implement the extended feature, since obviously D3dec
does not know anything about the concrete I
-implementation it decorates. Does this necessarily mean we have to use virtual inheritance? Or is there any template based trick to get around that but still have an (abstracted) sub-Interface Isub
?The obvious alternative is of course to cut the link between I
and Isub
, turning it into a trivial mix-in. This works, but is ugly, since Isub
does not make much sense on its own, independent of I
. Both even use the same data types on the signatures, etc...
Upvotes: 2
Views: 376
Reputation: 308206
You can avoid the diamond inheritance problem entirely by making the interface class a template parameter of the concrete class. Then there's no more need for virtual class inheritance.
class I { ... };
template<class Ifc>
class D3Impl : public Ifc
{ ... };
typedef D3Impl<I> D3;
class Isub : public I { ... };
class D3Dec : public D3Impl<Isub>
{ ... };
Upvotes: 2