[Uml-devel] ambiguity
P. Fleury
fleury at users.sourceforge.net
Wed Jan 15 17:52:04 UTC 2003
Andrew Sutton wrote:
>this is supposed to ensure that duplicate instances of the RefObject class do
>not exist in instances of derived types. so, in theory, returning a reference
>to a RefObject for an instance of AliasType will not result in an ambiguous
>base class error.
>
>
Yes, this is exactly the meaning of virtual inheritance. This is a
programming language specific issue, though, and it goes hand in hand
with the problem of the calling of constructors and destructors (and
their calling order). It is up to the compiler to guarantee that the
constructor is called once only, at least once, and in the order
specified by the language (in C++, after all the base classes have been
initialized).
>so far so good, right? maybe. all the classes with the exception of AliasType
>are abstract and *might* appear in other circular inheritance hierarchies.
>
Note that an inheritance graph is always directed, and having a directed
graph like the one you describe (or like the ones you can build with
inheritance), you never get a cycle in the graph-theory sense. If you
write code which has a cycle, the compiler will kindly let you know :-),
as in
class D2; // needing forward declaration of rinheritance is sort of
suspect in the first place
class Base : public D2 {};
class D1 : public Base {};
class D2 : public D1 {};
>the problem is easy to understand in small doses, but what about generalized
>references "mid-hierarchy". in the example given above, there are multiple
>instances of ModelElement in the AliasType class. if we wanted to return a
>reference to ModelElement for an AliasType, we'd probably get an ambiguous
>base class error. one solution might be to always virtually derive abstract
>base classes, but i don't know if that would work. i haven't seen any
>examples where the most derived class virtually derives its multiple bases.
>
>
Multiple inheritance is a tricky field, Stroustrup said it himself. It
should be used in small doses anyway, or not visible at a certain point
in the hierarchy tree (inheritance encapsulation if you will).
Because of this complexity, some languages have decided to not allow it
in the first place (like Java). Note that the concept of Java interfaces
(corresponding to pure virtual base class) does not lead to any
ambiguity, because there are no data members and you cannot make an
inheritance graph which has different implementations of a method in the
paths along the inheritance graph.
>furthermore, there seems to be some caveat the the most derived class must
>call the constructors for virtually derived classes. if the entire
>inheritance hierarchy (excepting non-abstract classes) is virtually derived,
>then the non-abstract classes would have to construct ever single class in
>the inheritance hierarchy.
>
>
The call to constructors is solved globally for a given class, and it
entirely a compiler issue (and guarantee). The compiler computes the
inheritance tree, then computes the constructor ordering, then calls
them in that order. The order of calls of constructor is not clearly
specified in the C++ book, but it is advised to not rely on the call
order of the different constructors.
>another good question is whether or not we find multiple instances of
>non-virtually derived Ref classes in instantiated objects. all the
>documentation that i've found indicates that the multiple instances of the
>virtual base class are "unified" (as opposed to distinct). if that's the
>case, are the base classes of the VBC also unified?
>
>
Sometimes you want them be unified, sometimes you want them to be
distinct. Therefore C++ gives you the virtual modified for inheritance.
But I think that the cases where multiple inheritance of public
non-pure-virtual classes is really needed can be easily counted. Using
pure-virtual base classes solves the problem (the Java interfaces),
using private inheritance mostly solves the problem too (inheritance of
the implementation only), and otherwise most problems turn out to be
solvable by aggregation and delegation, which do not have as many
pitfalls as multiple inheritance. A weak argument for avoiding the
problem, I know, but nonetheless a realistic one...
In my experience, I have used it only a single time, over the roughly
100'000 lines of C++ code I have written so far. And I did not miss it
in Java at all.
But does UML specify a way to indicate if the multiply inherited base
class is unified or not ? Will it in future ?
--Pascal
More information about the umbrello-devel
mailing list