views:

1034

answers:

12

Can anyone think of any situation to use multiple inheritance? Every case I can think of can be solved by the method operator

AnotherClass() { return this->something.anotherClass; }
+8  A: 

I find multiple inheritance particularly useful when using mixin classes.

As stated in Wikipedia:

In object-oriented programming languages, a mixin is a class that provides a certain functionality to be inherited by a subclass, but is not meant to stand alone.

An example of how our product uses mixin classes is for configuration save and restore purposes. There is an abstract mixin class which defines a set of pure virtual methods. Any class which is saveable inherits from the save/restore mixin class which automatically gives them the appropriate save/restore functionality.

But they may also inherit from other classes as part of their normal class structure, so it is quite common for these classes to use multiple inheritance in this respect.

An example of multiple inheritance:

class Animal
{
   virtual void KeepCool() const = 0;
}

class Vertebrate
{
   virtual void BendSpine() { };
}


class Dog : public Animal, public Vertebrate
{
   void KeepCool() { Pant(); }
}

What is most important when doing any form of public inheritance (single or multiple) is to respect the is a relationship. A class should only inherit from one or more classes if it "is" one of those objects. If it simply "contains" one of those objects, aggregation or composition should be used instead.

The example above is well structured because a dog is an animal, and also a vertebrate.

LeopardSkinPillBoxHat
That's not multiple inheritance. It is uses of interfaces, but C++ just happens to implement it in the same way.
erikkallen
@Erik - It is only an interface if the mixin class is completely abstract. In the code example I gave, Vertebrate::BendSpine() has an implementation, albeit an empty one. I would still call this multiple inheritance, even if it's not the best example.
LeopardSkinPillBoxHat
Wouldn't it make more sense for vertebrate to be a subclass of animal, and for Dog to just subclass Vertebrate. Last I checked, all Vertebrates were animals.
Kibbee
Kibbee is right, Vertebrate _are_ animals (-:
Henk Holterman
A better example like this would be FlyingCreature as the mixin. Most birds and some mammals (bats) would inherit from FlyingCreature as well as the Bird or Mammal base class. Similarly for other properties, that impact behaviour that cross the usual taxonomy.
Richard
Not the best example, but the point stands... rather than having a *deep* inheritance structure, which is overkill in many situations, you can inherit (or mixin) from the desired parent attributes and get the same result.
Andrew Vit
@Kibbee - that is a good point. Maybe it wasn't the best example of class hierarchy, but it was the best I could think of while I was editing the answer. Hopefully my point of how multiple inheritance supports mixins was still clear.
LeopardSkinPillBoxHat
+2  A: 

One case I worked on recently involved network enabled label printers. We need to print labels, so we have a class LabelPrinter. This class has virtual calls for printing several different labels. I also have a generic class for TCP/IP connected things, which can connect, send and receive. So, when I needed to implement a printer, it inherited from both the LabelPrinter class and the TcpIpConnector class.

Anders Öhrt
+2  A: 

I think fmsf example is a bad idea. A car is not a tire or an engine. You should be using composition for that.

MI (of implementation or interface) can be used to add functionality. These are often called mixin classes.. Imagine you have a GUI. There is view class that handles drawing and a Drag&Drop class that handles dragging. If you have an object that does both you would have a class like

class DropTarget{
 public void Drop(DropItem & itemBeingDropped);
...
}

class View{
  public void Draw();
...
}

/* View you can drop items on */
class DropView:View,DropTarget{

}
hacken
A: 

The following example is mostly something I see often in C++: sometimes it may be necessary due to utility classes that you need but because of their design cannot be used through composition (at least not efficiently or without making the code even messier than falling back on mult. inheritance). A good example is you have an abstract base class A and a derived class B, and B also needs to be a kind of serializable class, so it has to derive from, let's say, another abstract class called Serializable. It's possible to avoid MI, but if Serializable only contains a few virtual methods and needs deep access to the private members of B, then it may be worth muddying the inheritance tree just to avoid making friend declarations and giving away access to B's internals to some helper composition class.

Michel
+4  A: 

Most people use multiple-inheritance in the context of applying multiple interfaces to a class. This is the approach Java and C#, among others, enforce.

C++ allows you to apply multiple base classes fairly freely, in an is-a relationship between types. So, you can treat a derived object like any of its base classes.

Another use, as LeopardSkinPillBoxHat points out, is in mix-ins. An excellent example of this is the Loki library, from Andrei Alexandrescu's book Modern C++ Design. He uses what he terms policy classes that specify the behavior or the requirements of a given class through inheritance.

Yet another use is one that simplifies a modular approach that allows API-independence through the use of sister-class delegation in the oft-dreaded diamond hierarchy.

The uses for MI are many. The potential for abuse is even greater.

greyfade
+14  A: 

Most uses of full scale Multiple inheritance are for mixins. As an example:

class DraggableWindow : Window, Draggable { }
class SkinnableWindow : Window, Skinnable { }
class DraggableSkinnableWindow : Window, Draggable, Skinnable { }

etc...

In most cases, it's best to use multiple inheritance to do strictly interface inheritance.

class DraggableWindow : Window, IDraggable { }

Then you implement the IDraggable interface in your DraggableWindow class. It's WAY too hard to write good mixin classes.

The benefit of the MI approach (even if you are only using Interface MI) is that you can then treat all kinds of different Windows as Window objects, but have the flexibility to create things that would not be possible (or more difficult) with single inheritance.

For example, in many class frameworks you see something like this:

class Control { }
class Window : Control { }
class Textbox : Control { }

Now, suppose you wanted a Textbox with Window characteristics? Like being dragable, having a titlebar, etc... You could do something like this:

class WindowedTextbox : Control, IWindow, ITexbox { }

In the single ineritence model, you can't easily inherit from both Window and Textbox without having some problems with duplicate Control objects and other kinds of problems. You can also treat a WindowedTextbox as a Window, a Textbox, or a Control.

Also, to address your .anotherClass() idiom, .anotherClass() returns a different object, while multiple inheritance allows the same object to be used for different purposes.

Mystere Man
+2  A: 

Java has interfaces. C++ has not.

Therefore, multiple inheritance can be used to emulate the interface feature. If you're a C# and Java programmer, every time you use a class that extends a base class but also implements a few interfaces, you are sort of admitting multiple inheritance can be useful in some situations.

luiscubal
I agree with this :) Worst thing about learning C++ and then C# later on is the constraing of mixins. I sometimes find myself copy-paste implementing an mixin interface, which could be poor code or design for my part, but I can't think of anything else to do - and as a programmer you hate copy-paste
cwap
C++ emulates interfaces 100% with abstract classes. What "the interface feature" are you talking about? Java/C# version of multiple inheritance for interfaces?
Eugene Lazutkin
C++ does not have an 'interface' keyword, since it doesn't need it(it has multiple inheritance). If other languages such as Java and C# have interfaces, then multiple inheritance in C++ must have some use cases.
luiscubal
+2  A: 

I think it would be most useful for boilerplate code. For example, the IDisposable pattern is exactly the same for all classes in .NET. So why re-type that code over and over again?

Another example is ICollection. The vast majority of the interface methods are implemented exactly the same. There are only a couple of methods that are actually unique to your class.

Unfortunately multiple-inheritance is very easy to abuse. People will quickly start doing silly things like LabelPrinter class inherit from their TcpIpConnector class instead of merely contain it.

Jonathan Allen
Theoretically you are right but in practice it's very hard to get right. And the price (virtual inheritance constructors) is pretty high.
Henk Holterman
That price is only paid if you need to have a common based inherited through multiple inheritance branches. In practice this rarely happens (and becomes a non-issue if the repeated base has no state).
Richard
+1  A: 

It is true that composition of an interface (Java or C# like) plus forwarding to a helper can emulate many of the common uses of multiple inheritance (notably mixins). However this is done at the cost of that forwarding code being repeated (and violating DRY).

MI does open a number of difficult areas, and more recently some language designers have taken decisions that the potential pitfalls of MI outweigh the benefits.

Similarly one can argue against generics (heterogeneous containers do work, loops can be replaced with (tail) recursion) and almost any other feature of programming languages. Just because it is possible to work without a feature does not mean that that feature is valueless or cannot help to effectively express solutions.

A rich diversity of languages, and language families makes it easier for us as developers to pick good tools that solve the business problem at hand. My toolbox contains many items I rarely use, but on those occasions I do not want to treat everything as a nail.

Richard
If a language feature is potentially very useful, but will normally be badly abused, it will likely be present in C++ and absent in Java. Different language design philosophies.
David Thornley
+1  A: 

An example of how our product uses mixin classes is for configuration save and restore purposes. There is an abstract mixin class which defines a set of pure virtual methods. Any class which is saveable inherits from the save/restore mixin class which automatically gives them the appropriate save/restore functionality.

This example doesn't really illustrate the usefulness of multiple inheritance. What being defined here is an INTERFACE. Multiple inheritance allows you to inherit behavior as well. Which is the point of mixins.

An example; because of a need to preserve backwards compatibility I have to implement my own serialization methods.

So every object gets a Read and Store method like this.

Public Sub Store(ByVal File As IBinaryWriter)
Public Sub Read(ByVal File As IBinaryReader)

I also want to be able to assign and clone object as well. So I would like this on every object.

Public Sub Assign(ByVal tObject As <Class_Name>)
Public Function Clone() As <Class_Name>

Now in VB6 I have this code repeated over and over again.

Public Assign(ByVal tObject As ObjectClass)
    Me.State = tObject.State
End Sub

Public Function Clone() As ObjectClass
    Dim O As ObjectClass
    Set O = New ObjectClass
    O.State = Me.State
    Set Clone = 0
End Function

Public Property Get State() As Variant
    StateManager.Clear
    Me.Store StateManager
    State = StateManager.Data
End Property

Public Property Let State(ByVal RHS As Variant)
    StateManager.Data = RHS
    Me.Read StateManager
End Property

Note that Statemanager is a stream that read and stores byte arrays.

This code is repeated dozens of times.

Now in .NET i am able to get around this by using a combination of generics and inheritance. My object under the .NET version get Assign, Clone, and State when they inherit from MyAppBaseObject. But I don't like the fact that every object inherits from MyAppBaseObject.

I rather just mix in the the Assign Clone interface AND BEHAVIOR. Better yet mix in separately the Read and Store interface then being able to mix in Assign and Clone. It would be cleaner code in my opinion.

But the times where I reuse behavior are DWARFED by the time I use Interface. This is because the goal of most object hierarchies are NOT about reusing behavior but precisely defining the relationship between different objects. Which interfaces are designed for. So while it would be nice that C# (or VB.NET) had some ability to do this it isn't a show stopper in my opinion.

The whole reason that this is even an issue that that C++ fumbled the ball at first when it came to the interface vs inheritance issue. When OOP debuted everybody thought that behavior reuse was the priority. But this proved to be a chimera and only useful for specific circumstances, like making a UI framework.

Later the idea of mixins (and other related concepts in aspect oriented programming) were developed. Multiple inheritance was found useful in creating mix-ins. But C# was developed just before this was widely recognized. Likely an alternative syntax will be developed to do this.

RS Conley
+1  A: 

I suspect that in C++, MI is best use as part of a framework (the mix-in classes previously discussed). The only thing I know for sure is that every time I've tried to use it in my apps, I've ended up regretting the choice, and often tearing it out and replacing it with generated code.

MI is one more of those 'use it if you REALLY need it, but make sure you REALLY need it' tools.

Michael Kohne
A: 

I had to use it today, actually...

Here was my situation - I had a domain model represented in memory where an A contained zero or more Bs(represented in an array), each B has zero or more Cs, and Cs to Ds. I couldn't change the fact that they were arrays (the source for these arrays were from automatically generated code from the build process). Each instance needed to keep track of which index in the parent array they belonged in. They also needed to keep track of the instance of their parent (too much detail as to why). I wrote something like this (there was more to it, and this is not syntactically correct, it's just an example):

class Parent
{
    add(Child c)
    {
        children.add(c);
        c.index = children.Count-1;
        c.parent = this;
    }
    Collection<Child> children
}

class Child
{
    Parent p;
    int index;
}

Then, for the domain types, I did this:

class A : Parent
class B : Parent, Child
class C : Parent, Child
class D : Child

The actually implementation was in C# with interfaces and generics, and I couldn't do the multiple inheritance like I would have if the language supported it (some copy paste had to be done). So, I thought I'd search SO to see what people think of multiple inheritance, and I got your question ;)

I couldn't use your solution of the .anotherClass, because of the implementation of add for Parent (references this - and I wanted this to not be some other class).

It got worse because the generated code had A subclass something else that was neither a parent or a child...more copy paste.

paquetp
It seems you're making this more complex than necessary. Why not just have a "Node", which has one parent (that can be NULL) and multiple children (which could be empty). Then simply make A, B, C, and D all inherit from Node.
Andrew Shepherd
I wanted to be able to say that you can't reference the parent of an A or add to a child D (because A has no parent, and D has no children). With my implementation, it won't compile if you try. I also improved this with generics so that you can't add a C to an A, C or D, or if you reference the parent of a B, you won't need to cast it to an A (it will be an A already through generics), etc.
paquetp