![]() |
| How many eyes would Bee have? |
Both of those classes inherit from Animal! In your memory allocation, should C++ store room for two instances of Animal's variables, or just one? This is called the "Diamond Problem."
What does "the diamond problem" do?
In the above graphic I so generously made for the internet, it is shown that Animal has eyes, Winged has wings, and Legged has legs. Please draw your attention to the right, where non-virtual inheritance is used. Because both Winged and Legged have the superclass Animal, both of them inherit a number of eyes. This means that if Bee ran itsgetNumEyes method, you could easily get a compiler error because it wouldn't know which instance of Animal to pull from.Put another way: let's assume that all Animal instances have some method like
eat, which for some reason are overridden by both Winged and Legged, but not by Bee. When Bee calls eat, which overridden version will it use?Why does it exist?
Of course C++ needs to be versatile, and so the powers that be decided to solve the diamond problem of multiple inheritance by delegating more work to the programmer. Which makes it extremely versatile. And convoluted. And as with anything in engineering, any benefit comes with an equal cost. This is the principle of equivalent exchange.What does this allow you to do? Well, there are times where you may want a subclass to inherit the traits from both parents' (identical) parent classes
Java vs. C++
In Java, Bee's parent class would just be Animal, and it would implement the Winged and Legged methods—which don't concretely define any member variables, but declare that Bee must have a method to "calculate legs," or "calculate wings," and so forth. This seems like a good solution: write the program in a way where this problem does not occur.But don't fear! There is a solution in C++. Languages like Java eliminate the problem entirely by forcing a programmer to design their classes in a different way, but C++ is not like that. C++ is not a spear, where you just have to hold the long shaft and let the other end sort itself out. C++ is a samurai sword. It's very sharp and very powerful, but if you make one mistake you'll gut yourself. So don't gut yourself! Use virtual inheritance.
In the C++ solution, the inheritance from Animal to both Winged and Legged would be marked
virtual. So when you declare the class, you write class Winged : virtual public Animal. Doing this makes C++ create only one Animal object, so everything works correctly.Of course, by virtue of the fact that C++ doesn't have Java's
super keyword, multiple inheritance like this means that if you (for whatever reason) need to change the superclass, you'll have to change it everywhere. Sounds fun!Additional Reading
- Read more about it on the multiple inheritance and virtual inheritance pages on Wikipedia.
- Here's a pretty good Stack Overflow thread about the diamond problem.
- This blog post from ProgrammerInterview.com covers compiler errors in the diamond problem, with a code example.
- The page of C++ Frequently Questioned Answers has a lot of content on multiple and virtual inheritance.

No comments:
Post a Comment