Multiple Inheritance Interfaces and Code Reuse

T

Timie Milie

I have a tree of pure virtual classes with no data members or code
implementation (interfaces):

A
/ \
B C
/|\ /|\
/ | X | \
/ |/ \| \
D F G H
/ \
I J

(You'll need a fixed width font to view the ASCII art)

I also have an implementation class hierachy that mirrors the above
structure, i.e A --> AImpl, B--> BImpl and so on. Each implementation
class uses inheritance to add implementation functionality to its
parent class. Now I know the purpose of inheritance is code reuse, but
in this case it is very useful as each class merely extends
functionality and makes use of existing parent class functionality.

I tried using composition but it didn't scale well as I had to
implement every interface in the branch in each implementation classes
header - which were getting very large near the bottom of the tree.
Writing the implementation class also took ages as I had to wrap every
composited implementation function in an implementation class
function. I guess I could cut down on this using private inheritance
and the 'using' keyword? Multiple inheritance in the implementation
structure allowed me to keep my headers and source files smaller.

I am also having to use lots of virtual inheritance to share single
base classes.

As if that wasn't bad enough objects of class B can own a single
objects of class C (parent child relationships) via a (boost) shared
pointer. My copy constructor and assignment operators perform *deep*
copies.

I also use the virtual constructor idiom.

I also use the visitor pattern on the interface side. The latter
introduced nasty circular dependencies when just using implementation
classes that was fixed by using interfaces. Phew.

So here are my questions:

1. Is this actually going to end up being impossible to make work?
2. Is this really bad as opposed to generally ill advised?
3. Are there any easy to manage alternatives / have I misunderstood
composition or private inheritance?
4. What are the gotchas I have to watch out for if I continue down my
current path?

Thanks in advance,

TM
 
F

Francesco S. Carta

I have a tree of pure virtual classes with no data members or code
implementation (interfaces):

      A
     / \
    B   C
   /|\ /|\
  / | X | \
 /  |/ \|  \
D   F   G   H
       / \
      I   J

(You'll need a fixed width font to view the ASCII art)

I also have an implementation class hierachy that mirrors the above
structure, i.e A --> AImpl, B--> BImpl and so on. Each implementation
class uses inheritance to add implementation functionality to its
parent class. Now I know the purpose of inheritance is code reuse, but
in this case it is very useful as each class merely extends
functionality and makes use of existing parent class functionality.

I tried using composition but it didn't scale well as I had to
implement every interface in the branch in each implementation classes
header - which were getting very large near the bottom of the tree.
Writing the implementation class also took ages as I had to wrap every
composited implementation function in an implementation class
function. I guess I could cut down on this using private inheritance
and the 'using' keyword? Multiple inheritance in the implementation
structure allowed me to keep my headers and source files smaller.

I am also having to use lots of virtual inheritance to share single
base classes.

As if that wasn't bad enough objects of class B can own a single
objects of class C (parent child relationships) via a (boost) shared
pointer. My copy constructor and assignment operators perform *deep*
copies.

I also use the virtual constructor idiom.

I also use the visitor pattern on the interface side. The latter
introduced nasty circular dependencies when just using implementation
classes that was fixed by using interfaces. Phew.

So here are my questions:

1. Is this actually going to end up being impossible to make work?
2. Is this really bad as opposed to generally ill advised?
3. Are there any easy to manage alternatives / have I misunderstood
composition or private inheritance?
4. What are the gotchas I have to watch out for if I continue down my
current path?

Unfortunately I'm not that experienced with your issues. Some other
people here are, I wonder why you didn't get any reply yet. Whatever.

If you have the time to continue digging it by yourself and you can
post actual code with specific issues, you're likely to get good
advices. In case your needs are beyond the reasonably-maintainable
features of the language, you'll get such kind of opinions.

Consider that computers and languages are not omnipotent. Maybe what
you're trying to achieve cannot be "easily" done yet, with the current
available features, hence you could be "obliged" to cope with a
complex, hard to maintain hierarchy.

Just be more explicit and you'll likely get more advice - consider
that a hierarchy structure could have nothing wrong in itself, but its
application to a particular task can actually be partially or totally
wrong/unmaintainable.
Thanks in advance,

Never thank in advance. Eventually, thank people for reading your
post. If you get help, thank thereafter. People can see "thanking in
advance" as a warning that you won't be thanking them after having
been helped, and that's a bad way to appear.

Not that I care that much: that's just to help you getting help the
next time.
 
A

Alf P. Steinbach

* Timie Milie:
I have a tree of pure virtual classes with no data members or code
implementation (interfaces):

A
/ \
B C
/|\ /|\
/ | X | \
/ |/ \| \
D F G H
/ \
I J

(You'll need a fixed width font to view the ASCII art)

If these are interfaces and your lines denote public inheritance, then the F:B
and G:C derivations are superfluous.

Usually it's a design error to have deep inheritance of interfaces.


I also have an implementation class hierachy that mirrors the above
structure, i.e A --> AImpl, B--> BImpl and so on. Each implementation
class uses inheritance to add implementation functionality to its
parent class. Now I know the purpose of inheritance is code reuse, but
in this case it is very useful as each class merely extends
functionality and makes use of existing parent class functionality.

What's the problem?

I tried using composition but it didn't scale well as I had to
implement every interface in the branch in each implementation classes
header - which were getting very large near the bottom of the tree.
Writing the implementation class also took ages as I had to wrap every
composited implementation function in an implementation class
function. I guess I could cut down on this using private inheritance
and the 'using' keyword? Multiple inheritance in the implementation
structure allowed me to keep my headers and source files smaller.

I am also having to use lots of virtual inheritance to share single
base classes.

As if that wasn't bad enough objects of class B can own a single
objects of class C (parent child relationships) via a (boost) shared
pointer. My copy constructor and assignment operators perform *deep*
copies.

I also use the virtual constructor idiom.

I also use the visitor pattern on the interface side. The latter
introduced nasty circular dependencies when just using implementation
classes that was fixed by using interfaces. Phew.

So here are my questions:

1. Is this actually going to end up being impossible to make work?

It smells of bad design, but the impossible just takes more time.

2. Is this really bad as opposed to generally ill advised?
Probably.


3. Are there any easy to manage alternatives / have I misunderstood
composition or private inheritance?

You'd have to be more concrete in order to get any useful answer to that. We're
not telepaths.

4. What are the gotchas I have to watch out for if I continue down my
current path?

Again impossible to say: you haven't defined what your current path is.


Cheers & hth.,

- Alf
 
M

Michael Doubez

I have a tree of pure virtual classes with no data members or code
implementation (interfaces):

      A
     / \
    B   C
   /|\ /|\
  / | X | \
 /  |/ \|  \
D   F   G   H
       / \
      I   J

(You'll need a fixed width font to view the ASCII art)

I also have an implementation class hierachy that mirrors the above
structure, i.e A --> AImpl, B--> BImpl and so on. Each implementation
class uses inheritance to add implementation functionality to its
parent class. Now I know the purpose of inheritance is code reuse, but
in this case it is very useful as each class merely extends
functionality and makes use of existing parent class functionality.

I tried using composition but it didn't scale well as I had to
implement every interface in the branch in each implementation classes
header - which were getting very large near the bottom of the tree.
Writing the implementation class also took ages as I had to wrap every
composited implementation function in an implementation class
function. I guess I could cut down on this using private inheritance
and the 'using' keyword? Multiple inheritance in the implementation
structure allowed me to keep my headers and source files smaller.

I am also having to use lots of virtual inheritance to share single
base classes.

As if that wasn't bad enough objects of class B can own a single
objects of class C (parent child relationships) via a (boost) shared
pointer. My copy constructor and assignment operators perform *deep*
copies.

I also use the virtual constructor idiom.

I also use the visitor pattern on the interface side. The latter
introduced nasty circular dependencies when just using implementation
classes that was fixed by using interfaces. Phew.

So here are my questions:

1. Is this actually going to end up being impossible to make work?

How could we know ?

AFAIS visitor pattern makes modifying the hierarchy more difficult.
2. Is this really bad as opposed to generally ill advised?

Inheriting an implementation is usually bad design but since you are
only extending the functionalities (I assume you don't redefine
virtual functions) then you are in a pristine OO case. Nothing wrong
with inheritance.

The rest depends on what you express with your class and how that does
reflect your problem space.
3. Are there any easy to manage alternatives / have I misunderstood
composition or private inheritance?

Do you mean you privately inherits in your diagram ?
4. What are the gotchas I have to watch out for if I continue down my
current path?

Over-engineering :)

It is not clear why you inherit a class. If it is for code reuse, then
privately inheriting should happen only for some kind of bridge and if
so, I suspect this could be abstracted in another class/interface
since you have control over the whole hierarchy.

Ultimately, you are the only one to know what you are trying to solve
and the forces you balance so we cannot comment on your design.
 
P

Pascal J. Bourguignon

Timie Milie said:
A
/ \
B C
/|\ /|\
/ | X | \
/ |/ \| \
D F G H
/ \
I J


Do you really have a use in the rest of this program for 7 or 9 different interfaces?

Are B and C really that different?

If you have only one implementation for each of these interfaces, why
distinguish them? I would only have one class A instead of A and Aimpl.

I would fussion A, B and C, or possibly at least just B and C, to
avoid multiple inheritance. It is often possible to extend
meaningfully (or at least, non non-sensically) an interface.

For example, square root works only on positive numbers.
However, depending on the application, you could extend it as:

sqrt(x) = |x|^½

sqrt(x) = sgn(x) * |x|^½

sqrt(x) = x^½ if x>=0, 0 if x<0

etc. This is something that is routinely done in mathematics. x^0 is
a-priori meaningless. However, it is useful to define it to be 1,
since this allows the normal rule: x^0*x^n=x^(0+n)=x^n even when the
exponent is 0.

In the same way you could define the behavior of the interface defined
in B for objects of C sort, so that your program keeps working. Not
to say that you will give objects of C sort to parts of code expecting
a B, if that didn't correspond to a meaningful operation.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top