Pros :
- It sometimes allow more obvious modeling of a problem than other ways to model it.
- If the different parrents have orthogonal purpose, it can allow some kind of compositing
Cons :
- If the different parents don't have orthogonal purpose, it makes the type difficult to understand.
- It's not easy to understand how it is implemented in a language (any language).
In C++ a good example of multiple inheritance used to composite orthogonal features is when you use CRTP to, for example, setup a component system for a game.
I've started to write an example but I think a real world example is more worth looking at. Some code of Ogre3D uses multiple inheritance in a nice and very intuitive way. For example, the Mesh class inherit from both Resources and AnimationContainer. Resources expose the interface common to all resources and AnimationContainer expose the interface specific for manipulating a set of animations. They are not related, so it's easy to think about a Mesh as being a resource that in addition can conain a set of animations. Feels natural isn't it?
You can look at other examples in this library, like the way memory allocation is managed in a fined grain way by making classes inherit from variants of a CRTP class overloading new and delete.
As said, the main problems with multiple inheritance rises from mixing related concepts. It makes the language have to set complex implementations (see the way C++ allows to play with the diamond problem...) and the user not being sure what's happening in that implementation. For example, read this article explaining how it is implemented in C++.
Removing it from the language helps avoiding people who don't know how the language is inforced to make things bad. But it forces to think in a way that, sometimes, don't feel natural, even if it's edge cases, it happen more often that you might think.
In a very narrow sense, the answer is "Yes": assuming that your base classes or interfaces are designed for a single purpose, inheriting both of them does create a class with multiple responsibilities. However, whether or not it is "a bad thing" depends on the nature of the classes or interfaces that you are inheriting.
You can partition your classes and interfaces into two major groups - the ones addressing the essential complexity of your system, and the ones addressing its accidental complexity. If you inherit from more than one "essential complexity" classes, it is bad; if you inherit from one "essential" and one or more "accidental" classes, it is OK.
For example, in a billing system you could have classes for representing invoices and billing cycles (they address the essential complexity) and classes for persisting objects (they address the accidental complexity). If you inherit like this
class BillingCycleInvoice : public BillingCycle, public Invoice {
};
it is bad: your BillingCycleInvoice
has a mixed responsibility as it relates to the essential complexity of the system.
On the other hand, if you inherit like this
class PersistentInvoice : public Invoice, public PersistentObject {
};
your class is OK: technically, it services two concerns at once, but since only one of them is essential, you can write off inheriting the accidental one as the "cost of doing business".
Best Answer
My observation is that a lot of folk misuse multiple inheritance without working through composition type questions.
The "classic" OO example of a car leads to this problem. For example, we'll say that a car breaks down to the following parts:
so we'll define a class that looks like this:
All well and good, but it presents some significant problems with encapsulation and constructors / destructors. And it doesn't accurately represent what a car looks like in the real world.
If we start asking composition questions then we'll see some nuances here that weren't at first obvious.
So now our class can look something like this:
Which is also all well and good. But now we start scratching our heads and say "you know, I really wish that when I instantiate a car that it has to have tires, an engine, and a chassis."
So now we can turn Tires, Engine, and Chassis into interfaces and we'll have the following class. I'm prefixing the interfaces with "I" to make the distinction more clear.
Interfaces are like contracts. When a class implements an interface, it's guaranteeing it will provide certain methods and behaviors.
And now things really are all well and good. Our model of the car accurately reflects the real world representation of the same Object, including some guarantees about the resemblance between the two courtesy of the Interfaces. We have avoided the icky issues that multiple inheritance can create.
That's not to say that multiple inheritance is always bad. However, it's not really needed most of the time which is why languages like Java and C# don't allow for multiple inheritance.