How could I avoid diamond inheritance? - c++

I am currently working on a C++ design where I have this inheritance structure:
A
/ \
B C
Class A does the computations that are common to both classes B and C, and classes B and C are two different ways of initializing A.
I'd like to add some sort of hybrid initialization, i.e. a class D that would use methods from B and C.
However, I'd need to use diamond inheritance to be able to access B::init() and C::init() to set up the attributes of D.
I know I can avoid diamond problems using virtual inheritance, but I get runtime errors that I don't have when I copy manually the methods. Moreover, I have problems when trying to instantiate the classes B and C, and a colleague advised me to never use diamond inheritance in my designs.
Therefore, I'd like to find some kind of "clean" workaround, which I have not been able to do.
I could put all the initialization routines in class A, but for the moment they are separated nicely and I'd like to avoid having one big class where I can't really separate the distinct groups of functions of the classes B and C. EDIT after answer: This is what I chose, using different cpp files to split my "big" class into logical groups of methods.
I could also remove the inheritance links and replace them with friendship, where the methods of B and C are static and work on a pointer of type A*. This way, I could call B::init(A* a) and C::init(A* a) from D::init(A* a). However, I'd have to replace all the uses of _fooAttribute by a->_fooAttribute, which is a bit cumbersome and does not seem right.
What would you recommend ?

If your design calls for diamond inheritance, then that is what you need to do. People treat it as a "must not use" feature of C++, but the truth of the matter is that it is there, it is fully defined (if somewhat complex to understand), and if your problem space calls for it, you should use it.
In particular, I was not able to understand whether this is, indeed, a diamond inheritance. In particular, does it make sense for the A inside B and the A inside C to be the same instance of A? From your question it would appear that it is not. That Both B and C has a certain, different, way it makes sense to initialize A. If that is the case, this is not a diamond inheritance. Just make sure that B and C inherit A in a non-virtual inheritance.
With that said, make sure this is, indeed, what your design calls for. Can you honestly say that B is a A? That C? Can you honestly say that D is both a B and a C? If not, maybe making A a member of B, C or both, or making B or C members of D would make more sense.
If the only reason you are inheriting from A is as a way to extend A's provided methods, then consider simply making those methods a member of A. As stated above, while reducing code duplication is a worthy cause, the design should make sure that inheritance relationship is a is a relationship. Deviating from that is asking for trouble.

Inheritance is an "is a" relationship. If B is an A, then you're good. The same applies to C. From your description, you do not have this relationship. Instead, you have a utility class (A) that does computations. You might want to make this have static methods as it shouldn't need to store any data in itself, if it's truly a utility. There's nothing wrong with passing A an instance of B or C and having it access the properties that it needs using B->fooAttribute. However, you will probably want both B and C to implement a common interface so you don't have to know which one you're looking at.

Related

Multiple Inheritence in c++ [duplicate]

Is it a good concept to use multiple inheritance or can I do other things instead?
Multiple inheritance (abbreviated as MI) smells, which means that usually, it was done for bad reasons, and it will blow back in the face of the maintainer.
Summary
Consider composition of features, instead of inheritance
Be wary of the Diamond of Dread
Consider inheritance of multiple interfaces instead of objects
Sometimes, Multiple Inheritance is the right thing. If it is, then use it.
Be prepared to defend your multiple-inherited architecture in code reviews
1. Perhaps composition?
This is true for inheritance, and so, it's even more true for multiple inheritance.
Does your object really need to inherit from another? A Car does not need to inherit from an Engine to work, nor from a Wheel. A Car has an Engine and four Wheel.
If you use multiple inheritance to resolve these problems instead of composition, then you've done something wrong.
2. The Diamond of Dread
Usually, you have a class A, then B and C both inherit from A. And (don't ask me why) someone then decides that D must inherit both from B and C.
I've encountered this kind of problem twice in eight years, and it is amusing to see because of:
How much of a mistake it was from the beginning (In both cases, D should not have inherited from both B and C), because this was bad architecture (in fact, C should not have existed at all...)
How much maintainers were paying for that, because in C++, the parent class A was present twice in its grandchild class D, and thus, updating one parent field A::field meant either updating it twice (through B::field and C::field), or having something go silently wrong and crash, later (new a pointer in B::field, and delete C::field...)
Using the keyword virtual in C++ to qualify the inheritance avoids the double layout described above if this is not what you want, but anyway, in my experience, you're probably doing something wrong...
In Object hierarchy, you should try to keep the hierarchy as a Tree (a node has ONE parent), not as a graph.
More about the Diamond (edit 2017-05-03)
The real problem with the Diamond of Dread in C++ (assuming the design is sound - have your code reviewed!), is that you need to make a choice:
Is it desirable for the class A to exist twice in your layout, and what does it mean? If yes, then by all means inherit from it twice.
if it should exist only once, then inherit from it virtually.
This choice is inherent to the problem, and in C++, unlike other languages, you can actually do it without dogma forcing your design at language level.
But like all powers, with that power comes responsibility: Have your design reviewed.
3. Interfaces
Multiple inheritance of zero or one concrete classes, and zero or more interfaces is usually Okay, because you won't encounter the Diamond of Dread described above. In fact, this is how things are done in Java.
Usually, what you mean when C inherits from A and B is that users can use C as if it was an A, and/or as if it was a B.
In C++, an interface is an abstract class which has:
all its method declared pure virtual (suffixed by = 0) (removed the 2017-05-03)
no member variables
The Multiple inheritance of zero to one real object, and zero or more interfaces is not considered "smelly" (at least, not as much).
More about the C++ Abstract Interface (edit 2017-05-03)
First, the NVI pattern can be used to produce an interface, because the real criteria is to have no state (i.e. no member variables, except this). Your abstract interface's point is to publish a contract ("you can call me this way, and this way"), nothing more, nothing less. The limitation of having only abstract virtual methods should be a design choice, not an obligation.
Second, in C++, it makes sense to inherit virtually from abstract interfaces, (even with the additional cost/indirection). If you don't, and the interface inheritance appears multiple times in your hierarchy, then you'll have ambiguities.
Third, object orientation is great, but it is not The Only Truth Out ThereTM in C++. Use the right tools, and always remember you have other paradigms in C++ offering different kinds of solutions.
4. Do you really need Multiple Inheritance?
Sometimes, yes.
Usually, your C class is inheriting from A and B, and A and B are two unrelated objects (i.e. not in the same hierarchy, nothing in common, different concepts, etc.).
For example, you could have a system of Nodes with X,Y,Z coordinates, able to do a lot of geometric calculations (perhaps a point, part of geometric objects) and each Node is an Automated Agent, able to communicate with other agents.
Perhaps you already have access to two libraries, each with its own namespace (another reason to use namespaces... But you use namespaces, don't you?), one being geo and the other being ai
So you have your own own::Node derive both from ai::Agent and geo::Point.
This is the moment when you should ask yourself if you should not use composition instead. If own::Node is really really both a ai::Agent and a geo::Point, then composition will not do.
Then you'll need multiple inheritance, having your own::Node communicate with other agents according to their position in a 3D space.
(You'll note that ai::Agent and geo::Point are completely, totally, fully UNRELATED... This drastically reduces the danger of multiple inheritance)
Other cases (edit 2017-05-03)
There are other cases:
using (hopefully private) inheritance as implementation detail
some C++ idioms like policies could use multiple inheritance (when each part needs to communicate with the others through this)
the virtual inheritance from std::exception (Is Virtual Inheritance necessary for Exceptions?)
etc.
Sometimes you can use composition, and sometimes MI is better. The point is: You have a choice. Do it responsibly (and have your code reviewed).
5. So, should I do Multiple Inheritance?
Most of the time, in my experience, no. MI is not the right tool, even if it seems to work, because it can be used by the lazy to pile features together without realizing the consequences (like making a Car both an Engine and a Wheel).
But sometimes, yes. And at that time, nothing will work better than MI.
But because MI is smelly, be prepared to defend your architecture in code reviews (and defending it is a good thing, because if you're not able to defend it, then you should not do it).
From an interview with Bjarne Stroustrup:
People quite correctly say that you don't need multiple inheritance, because anything you can do with multiple inheritance you can also do with single inheritance. You just use the delegation trick I mentioned. Furthermore, you don't need any inheritance at all, because anything you do with single inheritance you can also do without inheritance by forwarding through a class. Actually, you don't need any classes either, because you can do it all with pointers and data structures. But why would you want to do that? When is it convenient to use the language facilities? When would you prefer a workaround? I've seen cases where multiple inheritance is useful, and I've even seen cases where quite complicated multiple inheritance is useful. Generally, I prefer to use the facilities offered by the language to doing workarounds
There's no reason to avoid it and it can be very useful in situations. You need to be aware of the potential issues though.
The biggest one being the diamond of death:
class GrandParent;
class Parent1 : public GrandParent;
class Parent2 : public GrandParent;
class Child : public Parent1, public Parent2;
You now have two "copies" of GrandParent within Child.
C++ has thought of this though and lets you do virtual inheritence to get around the issues.
class GrandParent;
class Parent1 : public virtual GrandParent;
class Parent2 : public virtual GrandParent;
class Child : public Parent1, public Parent2;
Always review your design, ensure you are not using inheritance to save on data reuse. If you can represent the same thing with composition (and typically you can) this is a far better approach.
See w:Multiple Inheritance.
Multiple inheritance has received
criticism and as such, is not
implemented in many languages.
Criticisms includes:
Increased complexity
Semantic ambiguity often summarized as the diamond
problem.
Not being able to explicitly inherit multiple times from a single
class
Order of inheritance changing class semantics.
Multiple inheritance in languages with
C++/Java style constructors
exacerbates the inheritance problem of
constructors and constructor chaining,
thereby creating maintenance and
extensibility problems in these
languages. Objects in inheritance
relationships with greatly varying
construction methods are hard to
implement under the constructor
chaining paradigm.
Modern way of resolving this to use interface (pure abstract class) like COM and Java interface.
I can do other things in place of this?
Yes, you can. I am going to steal from GoF.
Program to an Interface, not an Implementation
Prefer composition over inheritance
Public inheritance is an IS-A relationship, and sometimes a class will be an type of several different classes, and sometimes it's important to reflect this.
"Mixins" are also sometimes useful. They are generally small classes, usually not inheriting from anything, providing useful functionality.
As long as the inheritance hierarchy is fairly shallow (as it should almost always be), and well managed, you're unlikely to get the dreaded diamond inheritance. The diamond isn't a problem with all languages that use multiple inheritance, but C++'s treatment of it is frequently awkward and sometimes puzzling.
While I've run into cases where multiple inheritance is very handy, they're actually fairly rare. This is likely because I prefer to use other design methods when I don't really need multiple inheritance. I do prefer to avoid confusing language constructs, and it's easy to construct inheritance cases where you have to read the manual really well to figure out what's going on.
You shouldn't "avoid" multiple inheritance but you should be aware of problems that can arise such as the 'diamond problem' ( http://en.wikipedia.org/wiki/Diamond_problem ) and treat the power given to you with care, as you should with all powers.
At the risk of getting a bit abstract, I find it illuminating to think about inheritance within the frame of category theory.
If we think of all our classes and arrows between them denoting inheritance relations, then something like this
A --> B
means that class B derives from class A. Note that, given
A --> B, B --> C
we say C derives from B which derives from A, so C is also said to derive from A, thus
A --> C
Furthermore, we say that for every class A that trivially A derives from A, thus our inheritance model fulfills the definition of a category. In more traditional language, we have a category Class with objects all classes and morphisms the inheritance relations.
That's a bit of setup, but with that let's take a look at our Diamond of Doom:
C --> D
^ ^
| |
A --> B
It's a shady looking diagram, but it'll do. So D inherits from all of A, B, and C. Furthermore, and getting closer to addressing OP's question, D also inherits from any superclass of A. We can draw a diagram
C --> D --> R
^ ^
| |
A --> B
^
|
Q
Now, problems associated with the Diamond of Death here are when C and B share some property/method names and things get ambiguous; however, if we move any shared behavior into A then the ambiguity disappears.
Put in categorical terms, we want A, B and C to be such that if B and C inherit from Q then A can be rewritten as as subclass of Q. This makes A something called a pushout.
There is also a symmetric construction on D called a pullback. This is essentially the most general useful class you can construct which inherits from both B and C. That is, if you have any other class R multiply inheriting from B and C, then D is a class where R can be rewritten as as subclass of D.
Making sure your tips of the diamond are pullbacks and pushouts gives us a nice way to generically handle name-clashing or maintenance issues which might arise otherwise.
Note Paercebal's answer inspired this as his admonitions are implied by the above model given that we work in the full category Class of all possible classes.
I wanted to generalize his argument to something which shows how complicated multiple inheritance relationships can be both powerful and non-problematic.
TL;DR Think of the inheritance relationships in your program as forming a category. Then you can avoid Diamond of Doom problems by making multiply-inherited classes pushouts and symmetrically, making a common parent class which is a pullback.
We use Eiffel. We have excellent MI. No worries. No issues. Easily managed. There are times to NOT use MI. However, it useful more than people realize because they are: A) in a dangerous language that does not manage it well -OR- B) satisfied with how they've worked around MI for years and years -OR- C) other reasons (too numerous to list I am quite sure--see answers above).
For us, using Eiffel, MI is as natural as anything else and another fine tool in the toolbox. Frankly, we're quite unconcerned that no one else is using Eiffel. No worries. We are happy with what we have and invite you to have a look.
While you're looking: Take special note of Void-safety and the eradication of Null pointer dereferencing. While we're all dancing around MI, your pointers are getting lost! :-)
You should use it carefully, there are some cases, like the Diamond Problem, when things can go complicated.
(source: learncpp.com)
Every programming language has a slightly different treatment of object-oriented programming with pros and cons. C++'s version places the emphasis squarely on performance and has the accompanying downside that it is disturbingly easy to write invalid code - and this is true of multiple inheritance. As a consequence there is a tendency to steer programmers away from this feature.
Other people have addressed the question of what multiple inheritance isn't good for. But we have seen quite a few comments that more-or-less imply that the reason to avoid it is because it's not safe. Well, yes and no.
As is often true in C++, if you follow a basic guideline you can use it safely without having to "look over your shoulder" constantly. The key idea is that you distinguish a special kind of class definition called a "mix-in"; class is a mix-in if all its member functions are virtual (or pure virtual). Then you are allowed to inherit from a single main class and as many "mix-ins" as you like - but you should inherit mixins with the keyword "virtual". e.g.
class CounterMixin {
int count;
public:
CounterMixin() : count( 0 ) {}
virtual ~CounterMixin() {}
virtual void increment() { count += 1; }
virtual int getCount() { return count; }
};
class Foo : public Bar, virtual public CounterMixin { ..... };
My suggestion is that if you intend to use a class as a mix-in class you also adopt a naming convention to make it easy for anyone reading the code to see what's happening & to verify you're playing by the rules of the basic guideline. And you'll find it works much better if your mix-ins have default constructors too, just because of the way virtual base classes work. And remember to make all the destructors virtual too.
Note that my use of the word "mix-in" here isn't the same as the parameterised template class (see this link for a good explanation) but I think it is a fair use of the terminology.
Now I don't want to give the impression that this is the only way to use multiple inheritance safely. It's just one way that is fairly easy to check.
Uses and Abuses of Inheritance.
The article does a great job of explaining inheritance, and it's dangers.
Beyond the diamond pattern, multiple inheritance tends to make the object model harder to understand, which in turn increases maintenance costs.
Composition is intrinsically easy to understand, comprehend, and explain. It can get tedious to write code for, but a good IDE (it's been a few years since I've worked with Visual Studio, but certainly the Java IDEs all have great composition shortcut automating tools) should get you over that hurdle.
Also, in terms of maintenance, the "diamond problem" comes up in non-literal inheritance instances as well. For instance, if you have A and B and your class C extends them both, and A has a 'makeJuice' method which makes orange juice and you extend that to make orange juice with a twist of lime: what happens when the designer for 'B' adds a 'makeJuice' method which generates and electrical current? 'A' and 'B' may be compatible "parents" right now, but that doesn't mean they will always be so!
Overall, the maxim of tending to avoid inheritance, and especially multiple inheritance, is sound. As all maxims, there are exceptions, but you need to make sure that there is a flashing green neon sign pointing at any exceptions you code (and train your brain so that any time you see such inheritance trees you draw in your own flashing green neon sign), and that you check to make sure it all makes sense every once in a while.
The key issue with MI of concrete objects is that rarely do you have an object that legitimately should "Be an A AND be a B", so it is rarely the correct solution on logical grounds. Far more often, you have an object C that obeys "C can act as an A or a B", which you can achieve via interface inheritance & composition. But make no mistake- inheritance of multiple interfaces is still MI, just a subset of it.
For C++ in particular, the key weakness of the feature isn't the actual EXISTENCE of Multiple Inheritance, but some constructs it allows that are almost always malformed. For example, inheriting multiple copies of the same object like:
class B : public A, public A {};
is malformed BY DEFINITION. Translated into English this is "B is an A and an A". So, even in human language there's a severe ambiguity. Did you mean "B has 2 As" or just "B is an A"?. Allowing such pathological code, and worse making it a usage example, did C++ no favors when it came to making a case for keeping the feature in successor languages.
You can use composition in preference to inheritance.
The general feeling is that composition is better, and it's very well discussed.
it takes 4/8 bytes per class involved.
(One this pointer per class).
This might never be a concern, but if one day you have a micro data structure which is instanced billions of time it will be.

Diamond inheritance

Assume classes D and E and F all inherit from base class B, and that
class C inherits from D and E.
(i) How many copies of class B appear in class C?
(ii) How would using virtual inheritance change this scenario? Explain
your answer.
(iii) How does Java avoid the need for multiple inheritance for many
of the
situations where multiple inheritance might be used in C++?
Here are some of my current ideas, but I'm an by no means an expert on C++!
(i) If C inherits from D and E which are subclasses of B, then would D and E technically be copies of their super class? Then if C inherits from D and E that would mean there are 2 copies of B in C.
(ii) Using virtual is somewhat similar to using Abstract in Java (i think). Now given this, it would mean that there would not be multiple copies of B in C, as the instantiation would be cascaded down to the level it is needed. I am not sure how to word my explanation but say B has a function called print() which prints "i am B" and C overrides this function put prints "i am C". If you called print() on C without virtual you end up printing "i am B", using virtual would mean that it would print "i am C".
(iii) My idea here is that Java can use interfaces to avoid the use of multiple inheritance. You can implement multiple interfaces but you can only extend one Class. I'm not sure what else to add here, so any input or relevant resources would be helpful.
(i) and (iii) are right. In my experience anyway, most of the time in C++ when I've used multiple inheritance it's been because the bases were interfaces (a concept which doesn't have keyword support in C++, but it is a concept you can execute anyway).
The first sentence of (ii) is right, however your second sentence is talking about virtual functions, which is completely different to virtual inheritance. Virtual inheritance means that there is only one copy of B, and the D and E both have that same copy as their base. There is no difference in terms of functions, but the difference comes in terms of member variables (and base classes) of B.
If there is a function that prints out B's member variable foo; then in case (ii) this function always prints the same value because there is only one foo, but in case (i) calling that function from the D base class may print a different value to calling it from the E base class.
The term "diamond inheritance" wraps all this up in two words that serve as a good mnemonic :)
You seem to have mostly arrived at the right answers, though the reasoning needs work. The key issue at play here is the question of "how to lay out the memory of an instance of C if it inherits the same base class twice?"
i) There are 2 copies of the base class B in the memory layout for an object of type C. The example provided is a case of "diamond inheritance", because when you draw out the dependency/inheritance tree, you essentially draw a diamond. The "problem" with diamond inheritance is essentially to ask how to lay the object out in memory. C++ went with two approaches, a fast one, this, duplicating the data members, and a slower one, "virtual inheritance". The reason to take the non-virtual approach is that if you inherit a class that has no data members (what would be an interface in Java), then there is no problem with "duplicating the data members", because they do not exist (see my note at the bottom). It is also advisable to use non-virtual inheritance if your plan is to only use single inheritance.
ii) If you have a virtual class C, then that is the way of saying in the C++ language that you would like to have the compiler perform acts of heroism to ensure that only one copy of any/all base classes exist in the memory layout of your derived class; I believe this also incurs a slight performance hit. If you use any 'B' members from a 'C' instance now, it will always refer to the same place in memory. Note that virtual inheritance has no bearing on whether your functions are virtual.
Aside: This also is completely unrelated to the concept of a class being abstract. To make a class abstract in C++, set any method declaration = 0, as in void foo() = 0;; doing so for any method (including the destructor) is sufficient to make the entire class abstract.
iii) Java outright forbids it. In Java there is only single inheritance plus the ability to implement any number of interfaces. While interfaces do grant you the "is-a" relationship and the ability to have virtual functions, they implicitly avoid the issues that C++ has with data layouts and diamond inheritance, as an interface cannot add any data members, ipso facto: there is no confusion about how to resolve any data member's location.
An important extension to iii is to realize that virtual function call dispatch is not impacted at all if you happen to "implement the same interface twice". The reason is that the method will always do the same thing, even if there were multiple copies of it in your virtual table; it only acts on the data of your class, it does not itself contain data that needs to be disambiguated.

How to create union class structure?

Say class A had method do(); and class B had field data;. I wonder if there is a way (using Boost for example) to create a class union from A and B which would have method do() and field data?
Union has a specific meaning in c and c++, and it's not what you want. It sounds like you want is multiple inheritance, a class C that inherits from both A and B. Alternatively, you could also have a class C that contains instances of classes A and B. Oftentimes composition ("has-a") is preferable over inheritance ("is-a").
Not a chance in hell. This would require reflection, which does not currently exist in the C++ language, and even if it did, it's highly unlikely that anybody would have implemented such a thing because why would you even want to do that. The closest you can get is if you inherited from both classes.

Accessing methods of an object put inside a class

A class A possesses an instance c of a class C. Another class B has to modify c through C::setBlah(); method.
Is it bad to create an accessor C getC(); in A and then use A.getC().setBlah() ?
Or should I create a method A::setBlah(); that would call C::setBlah(); ? Isn't it annoying if there are several methods like that ?
As with most "is it bad to do X?" questions, the answer is that it depends entirely on a given situation.
Sometimes it might be a really bad idea to have a getC() sort of function because it breaks encapsulation. Other times it might be completely fine because encapsulation of that detail might be irrelevant, and writing a lot of wrapper functions increases the amount of code that you have to write.
Pick whichever makes the most sense for the given situation. In code that I've written, I've taken both approaches.
If you do go the getC() route, do make sure you return a reference; otherwise you'll be modifying a copy which doesn't sound like what you want. Or, you might consider making A::c public so that you don't need a function at all.
A third option to consider would be inheritance from C, which removes the need for getC() or wrapper functions in A.
A Method C getC(); creates a copy of c, so calling A.getC().setBlah() would modify the copy of c, not the c of A.
If C has many similar methods to be called by classes outside A, I would definitely not add these to A. I prefer to keep interfaces as minimal as possible. If these changes are related and are done together, you may add a dedicated single function to A to execute all calls to C at once and logically collect all these changes under an intuitive name.
Such a setup also raises the question: why does B need to touch A's member C? Maybe your design is not quite right - should C be a member of B rather than A?

Why should I avoid multiple inheritance in C++?

Is it a good concept to use multiple inheritance or can I do other things instead?
Multiple inheritance (abbreviated as MI) smells, which means that usually, it was done for bad reasons, and it will blow back in the face of the maintainer.
Summary
Consider composition of features, instead of inheritance
Be wary of the Diamond of Dread
Consider inheritance of multiple interfaces instead of objects
Sometimes, Multiple Inheritance is the right thing. If it is, then use it.
Be prepared to defend your multiple-inherited architecture in code reviews
1. Perhaps composition?
This is true for inheritance, and so, it's even more true for multiple inheritance.
Does your object really need to inherit from another? A Car does not need to inherit from an Engine to work, nor from a Wheel. A Car has an Engine and four Wheel.
If you use multiple inheritance to resolve these problems instead of composition, then you've done something wrong.
2. The Diamond of Dread
Usually, you have a class A, then B and C both inherit from A. And (don't ask me why) someone then decides that D must inherit both from B and C.
I've encountered this kind of problem twice in eight years, and it is amusing to see because of:
How much of a mistake it was from the beginning (In both cases, D should not have inherited from both B and C), because this was bad architecture (in fact, C should not have existed at all...)
How much maintainers were paying for that, because in C++, the parent class A was present twice in its grandchild class D, and thus, updating one parent field A::field meant either updating it twice (through B::field and C::field), or having something go silently wrong and crash, later (new a pointer in B::field, and delete C::field...)
Using the keyword virtual in C++ to qualify the inheritance avoids the double layout described above if this is not what you want, but anyway, in my experience, you're probably doing something wrong...
In Object hierarchy, you should try to keep the hierarchy as a Tree (a node has ONE parent), not as a graph.
More about the Diamond (edit 2017-05-03)
The real problem with the Diamond of Dread in C++ (assuming the design is sound - have your code reviewed!), is that you need to make a choice:
Is it desirable for the class A to exist twice in your layout, and what does it mean? If yes, then by all means inherit from it twice.
if it should exist only once, then inherit from it virtually.
This choice is inherent to the problem, and in C++, unlike other languages, you can actually do it without dogma forcing your design at language level.
But like all powers, with that power comes responsibility: Have your design reviewed.
3. Interfaces
Multiple inheritance of zero or one concrete classes, and zero or more interfaces is usually Okay, because you won't encounter the Diamond of Dread described above. In fact, this is how things are done in Java.
Usually, what you mean when C inherits from A and B is that users can use C as if it was an A, and/or as if it was a B.
In C++, an interface is an abstract class which has:
all its method declared pure virtual (suffixed by = 0) (removed the 2017-05-03)
no member variables
The Multiple inheritance of zero to one real object, and zero or more interfaces is not considered "smelly" (at least, not as much).
More about the C++ Abstract Interface (edit 2017-05-03)
First, the NVI pattern can be used to produce an interface, because the real criteria is to have no state (i.e. no member variables, except this). Your abstract interface's point is to publish a contract ("you can call me this way, and this way"), nothing more, nothing less. The limitation of having only abstract virtual methods should be a design choice, not an obligation.
Second, in C++, it makes sense to inherit virtually from abstract interfaces, (even with the additional cost/indirection). If you don't, and the interface inheritance appears multiple times in your hierarchy, then you'll have ambiguities.
Third, object orientation is great, but it is not The Only Truth Out ThereTM in C++. Use the right tools, and always remember you have other paradigms in C++ offering different kinds of solutions.
4. Do you really need Multiple Inheritance?
Sometimes, yes.
Usually, your C class is inheriting from A and B, and A and B are two unrelated objects (i.e. not in the same hierarchy, nothing in common, different concepts, etc.).
For example, you could have a system of Nodes with X,Y,Z coordinates, able to do a lot of geometric calculations (perhaps a point, part of geometric objects) and each Node is an Automated Agent, able to communicate with other agents.
Perhaps you already have access to two libraries, each with its own namespace (another reason to use namespaces... But you use namespaces, don't you?), one being geo and the other being ai
So you have your own own::Node derive both from ai::Agent and geo::Point.
This is the moment when you should ask yourself if you should not use composition instead. If own::Node is really really both a ai::Agent and a geo::Point, then composition will not do.
Then you'll need multiple inheritance, having your own::Node communicate with other agents according to their position in a 3D space.
(You'll note that ai::Agent and geo::Point are completely, totally, fully UNRELATED... This drastically reduces the danger of multiple inheritance)
Other cases (edit 2017-05-03)
There are other cases:
using (hopefully private) inheritance as implementation detail
some C++ idioms like policies could use multiple inheritance (when each part needs to communicate with the others through this)
the virtual inheritance from std::exception (Is Virtual Inheritance necessary for Exceptions?)
etc.
Sometimes you can use composition, and sometimes MI is better. The point is: You have a choice. Do it responsibly (and have your code reviewed).
5. So, should I do Multiple Inheritance?
Most of the time, in my experience, no. MI is not the right tool, even if it seems to work, because it can be used by the lazy to pile features together without realizing the consequences (like making a Car both an Engine and a Wheel).
But sometimes, yes. And at that time, nothing will work better than MI.
But because MI is smelly, be prepared to defend your architecture in code reviews (and defending it is a good thing, because if you're not able to defend it, then you should not do it).
From an interview with Bjarne Stroustrup:
People quite correctly say that you don't need multiple inheritance, because anything you can do with multiple inheritance you can also do with single inheritance. You just use the delegation trick I mentioned. Furthermore, you don't need any inheritance at all, because anything you do with single inheritance you can also do without inheritance by forwarding through a class. Actually, you don't need any classes either, because you can do it all with pointers and data structures. But why would you want to do that? When is it convenient to use the language facilities? When would you prefer a workaround? I've seen cases where multiple inheritance is useful, and I've even seen cases where quite complicated multiple inheritance is useful. Generally, I prefer to use the facilities offered by the language to doing workarounds
There's no reason to avoid it and it can be very useful in situations. You need to be aware of the potential issues though.
The biggest one being the diamond of death:
class GrandParent;
class Parent1 : public GrandParent;
class Parent2 : public GrandParent;
class Child : public Parent1, public Parent2;
You now have two "copies" of GrandParent within Child.
C++ has thought of this though and lets you do virtual inheritence to get around the issues.
class GrandParent;
class Parent1 : public virtual GrandParent;
class Parent2 : public virtual GrandParent;
class Child : public Parent1, public Parent2;
Always review your design, ensure you are not using inheritance to save on data reuse. If you can represent the same thing with composition (and typically you can) this is a far better approach.
See w:Multiple Inheritance.
Multiple inheritance has received
criticism and as such, is not
implemented in many languages.
Criticisms includes:
Increased complexity
Semantic ambiguity often summarized as the diamond
problem.
Not being able to explicitly inherit multiple times from a single
class
Order of inheritance changing class semantics.
Multiple inheritance in languages with
C++/Java style constructors
exacerbates the inheritance problem of
constructors and constructor chaining,
thereby creating maintenance and
extensibility problems in these
languages. Objects in inheritance
relationships with greatly varying
construction methods are hard to
implement under the constructor
chaining paradigm.
Modern way of resolving this to use interface (pure abstract class) like COM and Java interface.
I can do other things in place of this?
Yes, you can. I am going to steal from GoF.
Program to an Interface, not an Implementation
Prefer composition over inheritance
Public inheritance is an IS-A relationship, and sometimes a class will be an type of several different classes, and sometimes it's important to reflect this.
"Mixins" are also sometimes useful. They are generally small classes, usually not inheriting from anything, providing useful functionality.
As long as the inheritance hierarchy is fairly shallow (as it should almost always be), and well managed, you're unlikely to get the dreaded diamond inheritance. The diamond isn't a problem with all languages that use multiple inheritance, but C++'s treatment of it is frequently awkward and sometimes puzzling.
While I've run into cases where multiple inheritance is very handy, they're actually fairly rare. This is likely because I prefer to use other design methods when I don't really need multiple inheritance. I do prefer to avoid confusing language constructs, and it's easy to construct inheritance cases where you have to read the manual really well to figure out what's going on.
You shouldn't "avoid" multiple inheritance but you should be aware of problems that can arise such as the 'diamond problem' ( http://en.wikipedia.org/wiki/Diamond_problem ) and treat the power given to you with care, as you should with all powers.
At the risk of getting a bit abstract, I find it illuminating to think about inheritance within the frame of category theory.
If we think of all our classes and arrows between them denoting inheritance relations, then something like this
A --> B
means that class B derives from class A. Note that, given
A --> B, B --> C
we say C derives from B which derives from A, so C is also said to derive from A, thus
A --> C
Furthermore, we say that for every class A that trivially A derives from A, thus our inheritance model fulfills the definition of a category. In more traditional language, we have a category Class with objects all classes and morphisms the inheritance relations.
That's a bit of setup, but with that let's take a look at our Diamond of Doom:
C --> D
^ ^
| |
A --> B
It's a shady looking diagram, but it'll do. So D inherits from all of A, B, and C. Furthermore, and getting closer to addressing OP's question, D also inherits from any superclass of A. We can draw a diagram
C --> D --> R
^ ^
| |
A --> B
^
|
Q
Now, problems associated with the Diamond of Death here are when C and B share some property/method names and things get ambiguous; however, if we move any shared behavior into A then the ambiguity disappears.
Put in categorical terms, we want A, B and C to be such that if B and C inherit from Q then A can be rewritten as as subclass of Q. This makes A something called a pushout.
There is also a symmetric construction on D called a pullback. This is essentially the most general useful class you can construct which inherits from both B and C. That is, if you have any other class R multiply inheriting from B and C, then D is a class where R can be rewritten as as subclass of D.
Making sure your tips of the diamond are pullbacks and pushouts gives us a nice way to generically handle name-clashing or maintenance issues which might arise otherwise.
Note Paercebal's answer inspired this as his admonitions are implied by the above model given that we work in the full category Class of all possible classes.
I wanted to generalize his argument to something which shows how complicated multiple inheritance relationships can be both powerful and non-problematic.
TL;DR Think of the inheritance relationships in your program as forming a category. Then you can avoid Diamond of Doom problems by making multiply-inherited classes pushouts and symmetrically, making a common parent class which is a pullback.
We use Eiffel. We have excellent MI. No worries. No issues. Easily managed. There are times to NOT use MI. However, it useful more than people realize because they are: A) in a dangerous language that does not manage it well -OR- B) satisfied with how they've worked around MI for years and years -OR- C) other reasons (too numerous to list I am quite sure--see answers above).
For us, using Eiffel, MI is as natural as anything else and another fine tool in the toolbox. Frankly, we're quite unconcerned that no one else is using Eiffel. No worries. We are happy with what we have and invite you to have a look.
While you're looking: Take special note of Void-safety and the eradication of Null pointer dereferencing. While we're all dancing around MI, your pointers are getting lost! :-)
You should use it carefully, there are some cases, like the Diamond Problem, when things can go complicated.
(source: learncpp.com)
Every programming language has a slightly different treatment of object-oriented programming with pros and cons. C++'s version places the emphasis squarely on performance and has the accompanying downside that it is disturbingly easy to write invalid code - and this is true of multiple inheritance. As a consequence there is a tendency to steer programmers away from this feature.
Other people have addressed the question of what multiple inheritance isn't good for. But we have seen quite a few comments that more-or-less imply that the reason to avoid it is because it's not safe. Well, yes and no.
As is often true in C++, if you follow a basic guideline you can use it safely without having to "look over your shoulder" constantly. The key idea is that you distinguish a special kind of class definition called a "mix-in"; class is a mix-in if all its member functions are virtual (or pure virtual). Then you are allowed to inherit from a single main class and as many "mix-ins" as you like - but you should inherit mixins with the keyword "virtual". e.g.
class CounterMixin {
int count;
public:
CounterMixin() : count( 0 ) {}
virtual ~CounterMixin() {}
virtual void increment() { count += 1; }
virtual int getCount() { return count; }
};
class Foo : public Bar, virtual public CounterMixin { ..... };
My suggestion is that if you intend to use a class as a mix-in class you also adopt a naming convention to make it easy for anyone reading the code to see what's happening & to verify you're playing by the rules of the basic guideline. And you'll find it works much better if your mix-ins have default constructors too, just because of the way virtual base classes work. And remember to make all the destructors virtual too.
Note that my use of the word "mix-in" here isn't the same as the parameterised template class (see this link for a good explanation) but I think it is a fair use of the terminology.
Now I don't want to give the impression that this is the only way to use multiple inheritance safely. It's just one way that is fairly easy to check.
Uses and Abuses of Inheritance.
The article does a great job of explaining inheritance, and it's dangers.
Beyond the diamond pattern, multiple inheritance tends to make the object model harder to understand, which in turn increases maintenance costs.
Composition is intrinsically easy to understand, comprehend, and explain. It can get tedious to write code for, but a good IDE (it's been a few years since I've worked with Visual Studio, but certainly the Java IDEs all have great composition shortcut automating tools) should get you over that hurdle.
Also, in terms of maintenance, the "diamond problem" comes up in non-literal inheritance instances as well. For instance, if you have A and B and your class C extends them both, and A has a 'makeJuice' method which makes orange juice and you extend that to make orange juice with a twist of lime: what happens when the designer for 'B' adds a 'makeJuice' method which generates and electrical current? 'A' and 'B' may be compatible "parents" right now, but that doesn't mean they will always be so!
Overall, the maxim of tending to avoid inheritance, and especially multiple inheritance, is sound. As all maxims, there are exceptions, but you need to make sure that there is a flashing green neon sign pointing at any exceptions you code (and train your brain so that any time you see such inheritance trees you draw in your own flashing green neon sign), and that you check to make sure it all makes sense every once in a while.
The key issue with MI of concrete objects is that rarely do you have an object that legitimately should "Be an A AND be a B", so it is rarely the correct solution on logical grounds. Far more often, you have an object C that obeys "C can act as an A or a B", which you can achieve via interface inheritance & composition. But make no mistake- inheritance of multiple interfaces is still MI, just a subset of it.
For C++ in particular, the key weakness of the feature isn't the actual EXISTENCE of Multiple Inheritance, but some constructs it allows that are almost always malformed. For example, inheriting multiple copies of the same object like:
class B : public A, public A {};
is malformed BY DEFINITION. Translated into English this is "B is an A and an A". So, even in human language there's a severe ambiguity. Did you mean "B has 2 As" or just "B is an A"?. Allowing such pathological code, and worse making it a usage example, did C++ no favors when it came to making a case for keeping the feature in successor languages.
You can use composition in preference to inheritance.
The general feeling is that composition is better, and it's very well discussed.
it takes 4/8 bytes per class involved.
(One this pointer per class).
This might never be a concern, but if one day you have a micro data structure which is instanced billions of time it will be.