C++ – Code Reuse via Multiple Inheritance or Composition

cinheritanceinterfacesmultiple-inheritance

I originally asked this question on StackOverflow, but I was directed here, and I think my problem is perhaps as much conceptual as technical, so here goes.

If you’re defining a hierarchy of abstract class in C++, and then creating concrete subclasses with implementations, you could end up with abstract classes something like this, say:

  A
 / \
B1 B2

So the concrete classes then inherit like so:

B1   B2        B1   B2
 |    |         |    |
C1   C2        D1   D2

And this is all fine and dandy when Cn and Dn are just implementing the interfaces of Bn, or where say C1 and C2 implement the A interface differently.

However, if I want to have some shared functionality in C1 and C2, which comes from the A interface, where do I put it?

It can’t go in A, both because A is abstract and because Dn should not be inheriting it.

It seems like there’s a notional A_for_C implementation, but does this belong in another ancestor class? Or in a composed sibling class?

   _____A_____                       _____A_____
  /     |     \                     /     |     \
B1   A_for_C  B2        vs        B1     B2     A_for_C
 |_____/ \____ |                   |      |
C1            C2                  C1     C2

                               (C1 and C2 then each have an A_for_C and delegate)

The first one seems conceptually accurate, but requires virtual inheritance, while the second requires delegation. So both impose a performance hit despite there not being any real ambiguity.

Reading around the web, on this website I find it said

Some people believe that the purpose of inheritance is code reuse. In C++, this is wrong. Stated plainly, “inheritance is not for code reuse.”

How then should the implementation be shared?

Further thoughts

I found some relevant discussion in these questions:

I think utnapistim’s answer below is much pithier and to the point than these, and helped me mentally cut through a lot of what these other questions/answers discuss.

Inheritance is about agreeing to fulfil a contract. Multiple inheritance is fine if the subclass really does guarantee fulfilling the parent contracts.

Implementation, however, is only really the concern of the final object. Yes, it might be convenient to inherit the implementation sometimes, but that’s actually orthogonal to the interface, and there are various techniques for pulling in an implementation other than the default v-table-based approach, including:

(Which are, I think, equivalent except that one is compile-time and one is run-time.)

Best Answer

There are two aspects to your question:

§1. What is c++ inheritance for (if not for code reuse)?

The simplest answer to give here is "implementing a contract" (also see Liskov substitution principle and facade design pattern).

§2. How then should the implementation be shared?

Consider:

  • Encapsulation of an object, implementing common behavior to both branches (this is sometimes the best alternative to inheritance diamonds). Your A_for_C doesn't need to inherit from A.
  • Free functions (templated if your algorithm applies to multiple types).
  • Template classes (CRTP may be an alternative to a diamond inheritance pattern).
Related Topic