Re: Diamond Shape Inheritance
amit wrote:
I was reading about diamond shaped inheritance on wikipedia.
=======================
In object-oriented programming languages with multiple inheritance and
knowledge organization, the diamond problem is an ambiguity that
arises when two classes B and C inherit from A, and class D inherits
from both B and C. If a method in D calls a method defined in A (and
does not override the method), and B and C have overridden that method
differently, then from which class does it inherit: B, or C?
======================
That's not really the problem with diamond inheritance. You don't even
need diamond inheritance, just multiple inheritance without any common
base class to get that "problem". Simply have a function with the same
name in both base classes you are inheriting from, and you have an
ambiguity. The solution is that you have to explicitly specify which one
you want to call, ie. "B::foo();" or "C::foo();"
The real problem with diamond inheritance is that if the base class A
has a member variable, should this member variable be duplicated in D
(once for B and once for C) or not? Should we consider B and C
completely independent classes with nothing in common (in which case
each has its own instance of that member variable from A), or should the
variables from A be merged in D, so that they appear only once?
The problem is not really on the user code side, but on the compiler
side. What kind of technologies should the compiler use in order to
achieve the merging? The problem is that the geometry of eg. C will be
different if it's instantiated as itself compared to it being inside D,
when D is instantiated. Yet eg. some function could take a reference of
type C, and you could give it a true instance of C, or you could give it
an instance of D. Both are valid parameters to it. However, that member
variable from A is at different locations in these cases. How can the
function in question know where it actually is?
C++ solves this problem, but it requires for the user to make the
decision of whether he wants the members of A to be merged or to be
separate, and this is done by either inheriting B and C from A in the
regular way (the members of A will become separate in D) or by
inheriting B and C virtually from A (the members of A will be merged in D).
Question 1:
But it still does not answer the question raised... Lets assume Base
class (Class A) has a function called show(). Lets assume Class B and
C inherit A (virtually...) and override the function show(). Now
Suppose class D inherits both B and C (making a diamond shaped
inheritance) and we call show(). Which show will be called ?
B's Show or C'Show ?
This has nothing to do with diamond nor virtual inheritance. It's just
a question of ambiguity if both B and C have a function named the same.
In that case you have to explicitly specify which one should be called
by prefixing the function call with the class name, eg. B::show();
Question2:
In the explanation it mentions the following: " a D object would
actually contain two separate A objects".
Now my understanding of C++ is limited. I actually thought when
inheritance happens we have Just 1 object of derived class.
Now as per the above statement we have 3 objects: 1 derived class
object and 2 base class objects (possibly embedded in the derived
class object) !!
This kind of confused me. Is this true ?
Let's forget about virtual inheritance, and let's think about the
geometry of B. It will be like this:
B class:
contents of A
additions of B
Likewise C will be like this:
C class:
contents of A
additions of C
If we inherit D from both, its geometry will be:
D class:
contents of B
contents of C
additions of D
But, forgetting any virtual inheritance, that's the same as:
D class
contents of A
additions of B
contents of A
additions of C
additions of D
The contents of A will appear twice in D. Once for the B part and once
for the C part.
What virtual inheritance does is that it merges the two A parts in D
into one. This requires internal trickery to work properly.