views:

520

answers:

10

To be clear, I'm not asking if/why multiple inheritance is good or bad. I've heard a lot of arguments from both sides of that debate.

I'm wondering if there is any kind of design problem or scenario in C++ in which multiple inheritance is either the only way to accomplish something, or at least is the most optimal way over all other alternatives to the point that it wouldn't make sense to consider anything else.

Obviously, this question doesn't apply to languages that don't support multiple inheritance.

+8  A: 

You can't do policy-based design without multiple inheritance. So if policy-based design is the most elegant way to solve your problem, than that means you need multiple inheritance to solve your problem, over all other options.

Multiple-inheritance can be very useful if it's not misused (like everything, in any language).

GMan
Would this imply that policy-based design simply isn't possible in a language such as Java, or are there ways to work around it?
Jeff L
Actually, the linked article indicates that multiple inheritance is only the most common implementation pattern (with some significant advantages), not that it is absolutely required.
GalacticCowboy
@Jeff L: the 'Proxy' class in Java can be used as a workaround.
finnw
Not in the way policy-based design generally works, no I don't think Java can do it. It might be able to do the alternative, where there are member variables for each policy rather than inheriting from it, but this loses some advantages inheriting has. If Java can use templates like this at all, I don't know.
GMan
@GMan: With a bit of boilerplate in Java you could just delegate methods known at coding time (hence in particular any the host actually calls) to the policy objects, and have accessors for them. In the C++ version the host automatically expands its interface to include arbitrary functions desired by the user and bunged into their mixin classes. So I guess it depends whether you (or properly, Alexandrescu) consider this feature to be separable from the "policy pattern" as such, or an intrinsic part of it. In Java you can still allow users to recover the policy objects, downcast, and call.
Steve Jessop
You can do also policy based design without MI pretty easily in languages that support macros, e.g. LISP or Clojure
mikera
+5  A: 

There is a situation in which you would inherit from a class and maybe implement one or two interfaces in Java. This is something you would resolve with multiple inheritance in c++ I think.

Janusz
+2  A: 

I'd read up on Java Interfaces, and so on, to get a better idea as to the answer to this question. The idea behind an Interface is to create an abstract class that acts as a template for another class. the advantage, here, is that the templates can be combined within a concrete class. For example-

Parent class- FoodStore Subclass- CoffeeShop Subclass- Bakery

With this inheritance tree, a FoodStore can be a Bakery or a CoffeeShop but not both. But then what would we call a Starbucks?

Better way, IMO-

Parent Class- FoodStore Interface- CoffeeShop Interface- Bakery

public class Starbucks extends FoodStore implements CoffeeShop, Bakery { ... }

You'll have to know a bit of Java to understand that, but have at it. Interfaces are fairly elementary, IMO.

As a further musing, perhaps Interfaces are designed to obey "Don't repeat yourself." Obvious, now that I mention it.

SilentW
+3  A: 

Multiple inheritance is useful if you need to inherit behavior, not just contract. However, as other languages demonstrate, multiple inheritance is not the only way to solve that problem, at the expense of making your inheritance tree deeper. As such, scenarios where you must and may only use multiple inheritance would be pretty rare.

GalacticCowboy
A: 

As have been said on the other answers:

But also:

e.tadeu
+3  A: 

C++ streams use multiple inheritance: istream and ostream are both parents of iostream. Since they both inherit from ios_base, you have a diamond.

It's the only "reasonable" solution in the sense that it would be unreasonable for the streams part of the standard libraries to take the same line as the algorithms and collections. So ostream behaves polymorphically rather than being a "duck-typed" interface like Iterator(*).

As soon as you have dynamic polymorphism, you need multiple inheritance to implement more than one interface at the same time.

(*) Presumably this is because anything else would be a shambles. You have to be able to write actual functions which manipulate streams, rather than forcing users to have templates everywhere. This is because it's common to write to "some stream, I don't know what until runtime", but not to want to manipulate "some collection, I don't know what until runtime".

Steve Jessop
+1  A: 

When you want to inherit functionality rather than role, case in point boost::noncopyable (other languages that support this (unlike Java and C#) call this a mixin).

Motti
A: 

When you must combine two or more third-party class hierarchies, each of which requires that objects be derived from the hierarchy's own Base class, then lacking multiple inheritance will make your code complex and fiddly.

namespace Object_Database {
    class Object {
      public:
        virtual void store() ;
        virtual void fetch() ;
    };
}

namespace Reflectives {
    class Object {
      public:
        virtual std::vector<std::string> > membernames();
        virtual std::vector<std::string> > methodnames();
    };
}

The first hierarchy lets users create objects which can be serialized to and from an object database, and requires that all such objects be derived from class Object_Database::Object. The second hierarchy lets users create objects which can be queried at runtime for the names of their members, and requires that all such objects be derived from Reflectives::Object.

If you require objects that can do both, you just need to write:

  class ReflectivePickle : 
  public Object_Database::Object, 
  public Reflectives::Object {
    // ...
  };

The other solutions are unreasonable.

Thomas L Holaday
A: 

I tend to use multiple inheritance in C++ when the base classes are "interface classes", i.e. base classes where all methods are pure virtual, none have implementations [remember you can still define an implementation, but you have to invoke it explicitly], and there are no data members. Very similar to "interfaces" in Java or (from what I hear) C#.

To use polymorphism in C++, you can't use composition, you have to use (public) inheritance.

So if class Bar inherits (publicly) from Printable and Serializable, I can treat the object like a printable object, a serializable object, or a Bar object (using pointers or references).

With composition, you can't do that.

Dan
A: 

If you want to see a beautiful implementation of Multiple Inheritance check out Eiffel. They solve the diamond problem through feature renaming, far simpler than scope resolution and it even supports direct repeated inheritance such that:

A inherit B, B, B

when the need arises to use this type of inheritance.

Their Kernel library is open source and multiple inheritance is used extensively if you would like to see examples.

http://sourceforge.net/projects/eiffelstudio/files/