On Jan 17, 4:11 am, weird0 <amiredi...@gmail.comwrote:
How does C++ and C# solve the Diamond problem? With the help of
interfaces that is.
As others have pointed out, the diamond problem doesn't exist in C#
because there's no multiple inheritance (except with interfaces, which
are unaffected by this problem).
It exists in C++ because C++ does have multiple inheritance for
classes. For example, say you have a base class A which defines the
member "foo", two classes B and C which inherit from A and define the
members "bar" and "baz" respectively, and finally a derived class D
which derives from both B and C.
Now, the memory layout for a derived class normally consists of its
base class's layout plus ever new members are defined:
A's layout:
int foo
B's layout:
// copied from A
int foo
// introduced in B
int bar
C's layout:
// copied from A
int foo
// introduced in C
int baz
But then what does D look like? Well, it looks like both of its base
classes put together:
// copied from B
int foo
int bar
// copied from C
int foo
int baz
Notice that there are two "foo" members: that's the diamond problem.
Foo needs to be duplicated because the rules of inheritance say that a
D instance can be cast to an instance of either B or C (its bases).
That means its memory layout must contain a full instance of B and a
full instance of C. And that means that the methods D inherits from B
will see a *different* foo than the methods it inherits from C.
C++ solves the problem by introducing "virtual" base classes, which
don't have to appear in a fixed location in their derived classes'
memory layouts. By defining A as a *virtual* base of B and C, the
memory layouts might look like this instead:
B's layout II:
// copied from A
int foo
// introduced in B
<pointer to A>
int bar
C's layout II:
// copied from A
int foo
// introduced in C
<pointer to A>
int baz
Now when you define D as deriving from both B and C, the compiler only
needs to make one copy of foo, and update the other parts to point to
it:
D's layout II:
// copied from A
int foo
// copied from B
<pointer to A>
int bar
// copied from C
<pointer to A>
int baz
But there may be a performance impact, because now whenever any
methods of B or C access foo, they have to go through that pointer.
Since A is a virtual base class, the methods can't make any
assumptions about where its members will actually be located in
memory.
Also, notice that the decision of whether A should be virtualized is
made in B and C -- not in D, where the diamond problem actually
occurs. That's a pain.
Finally, it should be clear now why the diamond problem doesn't exist
with interfaces. Interfaces only hold method pointers, not data
members whose values might change, and so it doesn't matter if they're
duplicated: you can't get into the situation where some methods see
one value there and other methods see a different value, because the
values are set once and they never change.
Jesse